GCC Code Coverage Report


Directory: ./
File: sql/log_event.cc
Date: 2022-12-06 21:40:42
Exec Total Coverage
Lines: 5842 6406 91.2%
Branches: 5188 8708 59.6%

Line Branch Exec Source
1 /*
2 Copyright (c) 2000, 2022, Oracle and/or its affiliates.
3 Copyright (c) 2018, Percona and/or its affiliates.
4 Copyright (c) 2009, 2016, MariaDB
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2.0,
8 as published by the Free Software Foundation.
9
10 This program is also distributed with certain software (including
11 but not limited to OpenSSL) that is licensed under separate terms,
12 as designated in a particular file or component or in included license
13 documentation. The authors of MySQL hereby grant you an additional
14 permission to link the program and your derivative works with the
15 separately licensed software that they have included with MySQL.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License, version 2.0, for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
25
26 #define LOG_SUBSYSTEM_TAG "Repl"
27
28 #include "sql/log_event.h"
29
30 #include <assert.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33
34 #include "my_config.h"
35 #ifdef HAVE_SYS_TIME_H
36 #include <sys/time.h>
37 #endif
38 #include <algorithm>
39 #include <map>
40 #include <memory>
41 #include <string>
42 #include <utility>
43
44 #include "base64.h"
45 #include "decimal.h"
46 #include "libbinlogevents/export/binary_log_funcs.h" // my_timestamp_binary_length
47 #include "libbinlogevents/include/debug_vars.h"
48 #include "libbinlogevents/include/table_id.h"
49 #include "libbinlogevents/include/wrapper_functions.h"
50 #include "m_ctype.h"
51 #include "my_bitmap.h"
52 #include "my_byteorder.h"
53 #include "my_compiler.h"
54 #include "my_dbug.h"
55 #include "my_io.h"
56 #include "my_loglevel.h"
57 #include "my_macros.h"
58 #include "my_systime.h"
59 #include "my_table_map.h"
60 #include "my_time.h" // MAX_DATE_STRING_REP_LENGTH
61 #include "mysql.h" // MYSQL_OPT_MAX_ALLOWED_PACKET
62 #include "mysql/components/services/bits/psi_statement_bits.h"
63 #include "mysql/components/services/log_builtins.h"
64 #include "mysql/components/services/log_shared.h"
65 #include "mysql/psi/mysql_mutex.h"
66 #include "mysql/udf_registration_types.h"
67 #include "mysql_time.h"
68 #include "psi_memory_key.h"
69 #include "query_options.h"
70 #include "sql/auth/auth_acls.h"
71 #include "sql/binlog_reader.h"
72 #include "sql/field_common_properties.h"
73 #include "sql/my_decimal.h" // my_decimal
74 #include "sql/rpl_handler.h" // RUN_HOOK
75 #include "sql/rpl_tblmap.h"
76 #include "sql/sql_show_processlist.h" // pfs_processlist_enabled
77 #include "sql/system_variables.h"
78 #include "sql/tc_log.h"
79 #include "sql/xa/sql_cmd_xa.h" // Sql_cmd_xa_*
80 #include "sql_const.h"
81 #include "sql_string.h"
82 #include "template_utils.h"
83
84 #ifndef MYSQL_SERVER
85 #include "client/mysqlbinlog.h"
86 #include "sql-common/json_binary.h"
87 #include "sql-common/json_dom.h" // Json_wrapper
88 #include "sql/json_diff.h" // enum_json_diff_operation
89 #endif
90
91 #ifdef MYSQL_SERVER
92
93 #include <errno.h>
94 #include <fcntl.h>
95
96 #include <cstdint>
97 #include <new>
98
99 #include "libbinlogevents/include/binary_log.h" // binary_log
100 #include "my_base.h"
101 #include "my_command.h"
102 #include "my_dir.h" // my_dir
103 #include "my_sqlcommand.h"
104 #include "mysql/plugin.h"
105 #include "mysql/psi/mysql_cond.h"
106 #include "mysql/psi/mysql_file.h"
107 #include "mysql/psi/mysql_stage.h"
108 #include "mysql/psi/mysql_statement.h"
109 #include "mysql/psi/mysql_transaction.h"
110 #include "mysql/psi/psi_statement.h"
111 #include "mysqld_error.h"
112 #include "prealloced_array.h"
113 #include "sql/auth/auth_common.h"
114 #include "sql/auth/sql_security_ctx.h"
115 #include "sql/basic_ostream.h"
116 #include "sql/binlog.h"
117 #include "sql/current_thd.h"
118 #include "sql/dd/types/abstract_table.h" // dd::enum_table_type
119 #include "sql/debug_sync.h" // debug_sync_set_action
120 #include "sql/derror.h" // ER_THD
121 #include "sql/enum_query_type.h"
122 #include "sql/field.h"
123 #include "sql/handler.h"
124 #include "sql/item.h"
125 #include "sql/item_func.h" // Item_func_set_user_var
126 #include "sql/key.h"
127 #include "sql/log.h" // Log_throttle
128 #include "sql/mdl.h"
129 #include "sql/mysqld.h" // lower_case_table_names server_uuid ...
130 #include "sql/protocol.h"
131 #include "sql/rpl_msr.h" // channel_map
132 #include "sql/rpl_mta_submode.h" // Mts_submode
133 #include "sql/rpl_replica.h" // use_slave_mask
134 #include "sql/rpl_reporting.h"
135 #include "sql/rpl_rli.h" // Relay_log_info
136 #include "sql/rpl_rli_pdb.h" // Slave_job_group
137 #include "sql/sp_head.h" // sp_name
138 #include "sql/sql_base.h" // close_thread_tables
139 #include "sql/sql_bitmap.h"
140 #include "sql/sql_class.h"
141 #include "sql/sql_cmd.h"
142 #include "sql/sql_connect.h" //update_global_user_stats
143 #include "sql/sql_data_change.h"
144 #include "sql/sql_db.h" // load_db_opt_by_name
145 #include "sql/sql_digest_stream.h"
146 #include "sql/sql_error.h"
147 #include "sql/sql_exchange.h" // sql_exchange
148 #include "sql/sql_gipk.h"
149 #include "sql/sql_lex.h"
150 #include "sql/sql_list.h" // I_List
151 #include "sql/sql_load.h" // Sql_cmd_load_table
152 #include "sql/sql_locale.h" // my_locale_by_number
153 #include "sql/sql_parse.h" // mysql_test_parse_for_slave
154 #include "sql/sql_plugin.h" // plugin_foreach
155 #include "sql/sql_show.h" // append_identifier
156 #include "sql/sql_tablespace.h" // Sql_cmd_tablespace
157 #include "sql/table.h"
158 #include "sql/thd_raii.h" // Disable_index_extensions_switch_guard
159 #include "sql/transaction.h" // trans_rollback_stmt
160 #include "sql/transaction_info.h"
161 #include "sql/tztime.h" // Time_zone
162 #include "thr_lock.h"
163 #define window_size Log_throttle::LOG_THROTTLE_WINDOW_SIZE
164 Error_log_throttle slave_ignored_err_throttle(
165 window_size, INFORMATION_LEVEL, ER_SERVER_SLAVE_IGNORED_TABLE, "Repl",
166 "Error log throttle: %lu time(s) Error_code: 1237"
167 " \"Slave SQL thread ignored the query because of"
168 " replicate-*-table rules\" got suppressed.");
169 #endif /* MYSQL_SERVER */
170
171 #include "libbinlogevents/include/codecs/binary.h"
172 #include "libbinlogevents/include/codecs/factory.h"
173 #include "libbinlogevents/include/compression/iterator.h"
174 #include "mysqld_error.h"
175 #include "sql/rpl_gtid.h"
176 #include "sql/rpl_record.h" // enum_row_image_type, Bit_reader
177 #include "sql/rpl_utility.h"
178 #include "sql/xa_aux.h"
179
180 struct mysql_mutex_t;
181
182 PSI_memory_key key_memory_log_event;
183 PSI_memory_key key_memory_Incident_log_event_message;
184 PSI_memory_key key_memory_Rows_query_log_event_rows_query;
185
186 using std::max;
187 using std::min;
188
189 /**
190 BINLOG_CHECKSUM variable.
191 */
192 const char *binlog_checksum_type_names[] = {"NONE", "CRC32", NullS};
193
194 unsigned int binlog_checksum_type_length[] = {sizeof("NONE") - 1,
195 sizeof("CRC32") - 1, 0};
196
197 TYPELIB binlog_checksum_typelib = {
198 array_elements(binlog_checksum_type_names) - 1, "",
199 binlog_checksum_type_names, binlog_checksum_type_length};
200
201 #define log_cs &my_charset_latin1
202
203 /*
204 Size of buffer for printing a double in format %.<PREC>g
205
206 optional '-' + optional zero + '.' + PREC digits + 'e' + sign +
207 exponent digits + '\0'
208 */
209 #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1)
210
211 #if defined(MYSQL_SERVER)
212 static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD *thd);
213
214 367 static const char *HA_ERR(int i) {
215 /*
216 This function should only be called in case of an error
217 was detected
218 */
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 367 times.
367 assert(i != 0);
220
8/56
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 15 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 102 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 13 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 4 times.
✓ Branch 29 taken 4 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✓ Branch 55 taken 127 times.
367 switch (i) {
221 32 case HA_ERR_KEY_NOT_FOUND:
222 32 return "HA_ERR_KEY_NOT_FOUND";
223 70 case HA_ERR_FOUND_DUPP_KEY:
224 70 return "HA_ERR_FOUND_DUPP_KEY";
225 case HA_ERR_RECORD_CHANGED:
226 return "HA_ERR_RECORD_CHANGED";
227 case HA_ERR_WRONG_INDEX:
228 return "HA_ERR_WRONG_INDEX";
229 case HA_ERR_CRASHED:
230 return "HA_ERR_CRASHED";
231 case HA_ERR_WRONG_IN_RECORD:
232 return "HA_ERR_WRONG_IN_RECORD";
233 case HA_ERR_OUT_OF_MEM:
234 return "HA_ERR_OUT_OF_MEM";
235 case HA_ERR_NOT_A_TABLE:
236 return "HA_ERR_NOT_A_TABLE";
237 case HA_ERR_WRONG_COMMAND:
238 return "HA_ERR_WRONG_COMMAND";
239 case HA_ERR_OLD_FILE:
240 return "HA_ERR_OLD_FILE";
241 case HA_ERR_NO_ACTIVE_RECORD:
242 return "HA_ERR_NO_ACTIVE_RECORD";
243 case HA_ERR_RECORD_DELETED:
244 return "HA_ERR_RECORD_DELETED";
245 case HA_ERR_RECORD_FILE_FULL:
246 return "HA_ERR_RECORD_FILE_FULL";
247 case HA_ERR_INDEX_FILE_FULL:
248 return "HA_ERR_INDEX_FILE_FULL";
249 15 case HA_ERR_END_OF_FILE:
250 15 return "HA_ERR_END_OF_FILE";
251 case HA_ERR_UNSUPPORTED:
252 return "HA_ERR_UNSUPPORTED";
253 case HA_ERR_TOO_BIG_ROW:
254 return "HA_ERR_TOO_BIG_ROW";
255 case HA_WRONG_CREATE_OPTION:
256 return "HA_WRONG_CREATE_OPTION";
257 case HA_ERR_FOUND_DUPP_UNIQUE:
258 return "HA_ERR_FOUND_DUPP_UNIQUE";
259 case HA_ERR_UNKNOWN_CHARSET:
260 return "HA_ERR_UNKNOWN_CHARSET";
261 case HA_ERR_WRONG_MRG_TABLE_DEF:
262 return "HA_ERR_WRONG_MRG_TABLE_DEF";
263 case HA_ERR_CRASHED_ON_REPAIR:
264 return "HA_ERR_CRASHED_ON_REPAIR";
265 case HA_ERR_CRASHED_ON_USAGE:
266 return "HA_ERR_CRASHED_ON_USAGE";
267 102 case HA_ERR_LOCK_WAIT_TIMEOUT:
268 102 return "HA_ERR_LOCK_WAIT_TIMEOUT";
269 case HA_ERR_LOCK_TABLE_FULL:
270 return "HA_ERR_LOCK_TABLE_FULL";
271 case HA_ERR_READ_ONLY_TRANSACTION:
272 return "HA_ERR_READ_ONLY_TRANSACTION";
273 13 case HA_ERR_LOCK_DEADLOCK:
274 13 return "HA_ERR_LOCK_DEADLOCK";
275 case HA_ERR_CANNOT_ADD_FOREIGN:
276 return "HA_ERR_CANNOT_ADD_FOREIGN";
277 4 case HA_ERR_NO_REFERENCED_ROW:
278 4 return "HA_ERR_NO_REFERENCED_ROW";
279 4 case HA_ERR_ROW_IS_REFERENCED:
280 4 return "HA_ERR_ROW_IS_REFERENCED";
281 case HA_ERR_NO_SAVEPOINT:
282 return "HA_ERR_NO_SAVEPOINT";
283 case HA_ERR_NON_UNIQUE_BLOCK_SIZE:
284 return "HA_ERR_NON_UNIQUE_BLOCK_SIZE";
285 case HA_ERR_NO_SUCH_TABLE:
286 return "HA_ERR_NO_SUCH_TABLE";
287 case HA_ERR_TABLE_EXIST:
288 return "HA_ERR_TABLE_EXIST";
289 case HA_ERR_NO_CONNECTION:
290 return "HA_ERR_NO_CONNECTION";
291 case HA_ERR_NULL_IN_SPATIAL:
292 return "HA_ERR_NULL_IN_SPATIAL";
293 case HA_ERR_TABLE_DEF_CHANGED:
294 return "HA_ERR_TABLE_DEF_CHANGED";
295 case HA_ERR_NO_PARTITION_FOUND:
296 return "HA_ERR_NO_PARTITION_FOUND";
297 case HA_ERR_RBR_LOGGING_FAILED:
298 return "HA_ERR_RBR_LOGGING_FAILED";
299 case HA_ERR_DROP_INDEX_FK:
300 return "HA_ERR_DROP_INDEX_FK";
301 case HA_ERR_FOREIGN_DUPLICATE_KEY:
302 return "HA_ERR_FOREIGN_DUPLICATE_KEY";
303 case HA_ERR_TABLE_NEEDS_UPGRADE:
304 return "HA_ERR_TABLE_NEEDS_UPGRADE";
305 case HA_ERR_TABLE_READONLY:
306 return "HA_ERR_TABLE_READONLY";
307 case HA_ERR_AUTOINC_READ_FAILED:
308 return "HA_ERR_AUTOINC_READ_FAILED";
309 case HA_ERR_AUTOINC_ERANGE:
310 return "HA_ERR_AUTOINC_ERANGE";
311 case HA_ERR_GENERIC:
312 return "HA_ERR_GENERIC";
313 case HA_ERR_RECORD_IS_THE_SAME:
314 return "HA_ERR_RECORD_IS_THE_SAME";
315 case HA_ERR_LOGGING_IMPOSSIBLE:
316 return "HA_ERR_LOGGING_IMPOSSIBLE";
317 case HA_ERR_CORRUPT_EVENT:
318 return "HA_ERR_CORRUPT_EVENT";
319 case HA_ERR_ROWS_EVENT_APPLY:
320 return "HA_ERR_ROWS_EVENT_APPLY";
321 case HA_ERR_FK_DEPTH_EXCEEDED:
322 return "HA_ERR_FK_DEPTH_EXCEEDED";
323 case HA_ERR_INNODB_READ_ONLY:
324 return "HA_ERR_INNODB_READ_ONLY";
325 case HA_ERR_COMPUTE_FAILED:
326 return "HA_ERR_COMPUTE_FAILED";
327 case HA_ERR_NO_WAIT_LOCK:
328 return "HA_ERR_NO_WAIT_LOCK";
329 case HA_ERR_FTS_TOO_MANY_NESTED_EXP:
330 return "HA_ERR_FTS_TOO_MANY_NESTED_EXP";
331 }
332 127 return "No Error!";
333 }
334
335 /**
336 Error reporting facility for Rows_log_event::do_apply_event
337
338 @param level error, warning or info
339 @param ha_error HA_ERR_ code
340 @param rli pointer to the active Relay_log_info instance
341 @param thd pointer to the slave thread's thd
342 @param table pointer to the event's table object
343 @param type the type of the event
344 @param log_name the master binlog file name
345 @param pos the master binlog file pos (the next after the event)
346
347 */
348 371 static void inline slave_rows_error_report(enum loglevel level, int ha_error,
349 Relay_log_info const *rli, THD *thd,
350 TABLE *table, const char *type,
351 const char *log_name, ulong pos) {
352
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 4 times.
371 const char *handler_error = (ha_error ? HA_ERR(ha_error) : nullptr);
353 bool is_group_replication_applier_channel =
354
1/2
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
371 channel_map.is_group_replication_channel_name(
355 371 (const_cast<Relay_log_info *>(rli))->get_channel(), true);
356 char buff[MAX_SLAVE_ERRMSG], *slider;
357 372 const char *buff_end = buff + sizeof(buff);
358 size_t len;
359 Diagnostics_area::Sql_condition_iterator it =
360
1/2
✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
372 thd->get_stmt_da()->sql_conditions();
361 const Sql_condition *err;
362 372 buff[0] = 0;
363
364
5/6
✓ Branch 0 taken 371 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 398 times.
✓ Branch 3 taken 372 times.
✓ Branch 4 taken 397 times.
✓ Branch 5 taken 1 times.
771 for (err = it++, slider = buff; err && slider < buff_end - 1;
365 399 slider += len, err = it++) {
366
1/2
✓ Branch 0 taken 399 times.
✗ Branch 1 not taken.
397 len = snprintf(slider, buff_end - slider, " %s, Error_code: %d;",
367 err->message_text(), err->mysql_errno());
368 }
369
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 356 times.
373 if (is_group_replication_applier_channel) {
370
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if (ha_error != 0) {
371
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
34 rli->report(level,
372
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 thd->is_error() ? thd->get_stmt_da()->mysql_errno()
373 : ER_UNKNOWN_ERROR,
374 "Could not execute %s event on table %s.%s;"
375 "%s handler error %s",
376
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 type, table->s->db.str, table->s->table_name.str, buff,
377 handler_error == nullptr ? "<unknown>" : handler_error);
378 } else {
379 rli->report(level,
380 thd->is_error() ? thd->get_stmt_da()->mysql_errno()
381 : ER_UNKNOWN_ERROR,
382 "Could not execute %s event on table %s.%s;"
383 "%s",
384 type, table->s->db.str, table->s->table_name.str, buff);
385 }
386 } else {
387
2/2
✓ Branch 0 taken 350 times.
✓ Branch 1 taken 6 times.
356 if (ha_error != 0) {
388
2/4
✓ Branch 0 taken 350 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 352 times.
✗ Branch 3 not taken.
702 rli->report(level,
389
1/2
✓ Branch 0 taken 351 times.
✗ Branch 1 not taken.
351 thd->is_error() ? thd->get_stmt_da()->mysql_errno()
390 : ER_UNKNOWN_ERROR,
391 "Could not execute %s event on table %s.%s;"
392 "%s handler error %s; "
393 "the event's master log %s, end_log_pos %lu",
394
1/2
✓ Branch 0 taken 351 times.
✗ Branch 1 not taken.
350 type, table->s->db.str, table->s->table_name.str, buff,
395 handler_error == nullptr ? "<unknown>" : handler_error,
396 log_name, pos);
397 } else {
398
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 rli->report(level,
399
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 thd->is_error() ? thd->get_stmt_da()->mysql_errno()
400 : ER_UNKNOWN_ERROR,
401 "Could not execute %s event on table %s.%s;"
402 "%s the event's master log %s, end_log_pos %lu",
403
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
6 type, table->s->db.str, table->s->table_name.str, buff,
404 log_name, pos);
405 }
406 }
407 373 }
408
409 /**
410 Set the rewritten database, or current database if it should not be
411 rewritten, into THD.
412
413 @param thd THD handle
414 @param db database name
415 @param db_len the length of database name
416
417 @retval true if the passed db is rewritten.
418 @retval false if the passed db is not rewritten.
419 */
420 567510 static bool set_thd_db(THD *thd, const char *db, size_t db_len) {
421 567510 bool need_increase_counter = false;
422 char lcase_db_buf[NAME_LEN + 1];
423 LEX_CSTRING new_db;
424 567510 new_db.length = db_len;
425
2/2
✓ Branch 0 taken 223 times.
✓ Branch 1 taken 567287 times.
567510 if (lower_case_table_names) {
426 223 my_stpcpy(lcase_db_buf, db);
427
1/2
✓ Branch 0 taken 223 times.
✗ Branch 1 not taken.
223 my_casedn_str(system_charset_info, lcase_db_buf);
428 223 new_db.str = lcase_db_buf;
429 } else
430 567287 new_db.str = db;
431
432 /* This function is called by a slave thread. */
433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 567510 times.
567510 assert(thd->rli_slave);
434
435 567510 Rpl_filter *rpl_filter = thd->rli_slave->rpl_filter;
436
1/2
✓ Branch 0 taken 567542 times.
✗ Branch 1 not taken.
567510 new_db.str = rpl_filter->get_rewrite_db(new_db.str, &new_db.length);
437
438
2/2
✓ Branch 0 taken 223 times.
✓ Branch 1 taken 567319 times.
567542 if (lower_case_table_names) {
439 /* lcase_db_buf != new_db.str means that lcase_db_buf is rewritten. */
440
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 203 times.
223 if (strcmp(lcase_db_buf, new_db.str)) need_increase_counter = true;
441 } else {
442 /* db != new_db.str means that db is rewritten. */
443
2/2
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 567112 times.
567319 if (strcmp(db, new_db.str)) need_increase_counter = true;
444 }
445
446
1/2
✓ Branch 0 taken 567646 times.
✗ Branch 1 not taken.
567542 thd->set_db(new_db);
447
448 567646 return need_increase_counter;
449 }
450
451 #endif
452
453 /*
454 pretty_print_str()
455 */
456
457 #ifndef MYSQL_SERVER
458 168 static inline void pretty_print_str(IO_CACHE *cache, const char *str,
459 size_t len, bool identifier) {
460 168 const char *end = str + len;
461
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 84 times.
168 my_b_printf(cache, identifier ? "`" : "\'");
462
2/2
✓ Branch 0 taken 4134 times.
✓ Branch 1 taken 168 times.
4302 while (str < end) {
463 char c;
464
5/9
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 228 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 3903 times.
4134 switch ((c = *str++)) {
465 case '\n':
466 my_b_printf(cache, "\\n");
467 break;
468 case '\r':
469 my_b_printf(cache, "\\r");
470 break;
471 1 case '\\':
472 1 my_b_printf(cache, "\\\\");
473 1 break;
474 case '\b':
475 my_b_printf(cache, "\\b");
476 break;
477 case '\t':
478 my_b_printf(cache, "\\t");
479 break;
480 1 case '\'':
481 1 my_b_printf(cache, "\\'");
482 1 break;
483 228 case 0:
484 228 my_b_printf(cache, "\\0");
485 228 break;
486 1 case '`':
487
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (identifier)
488 1 my_b_printf(cache, "``");
489 else
490 my_b_printf(cache, "`");
491 1 break;
492 3903 default:
493 3903 my_b_printf(cache, "%c", c);
494 3903 break;
495 }
496 }
497
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 84 times.
168 my_b_printf(cache, identifier ? "`" : "\'");
498 168 }
499
500 /**
501 Print src as an string enclosed with "'"
502
503 @param[out] cache IO_CACHE where the string will be printed.
504 @param[in] str the string will be printed.
505 @param[in] len length of the string.
506 */
507 84 static inline void pretty_print_str(IO_CACHE *cache, const char *str,
508 size_t len) {
509 84 pretty_print_str(cache, str, len, false);
510 84 }
511
512 /**
513 Print src as an identifier enclosed with "`"
514
515 @param[out] cache IO_CACHE where the identifier will be printed.
516 @param[in] str the string will be printed.
517 @param[in] len length of the string.
518 */
519 84 static inline void pretty_print_identifier(IO_CACHE *cache, const char *str,
520 size_t len) {
521 84 pretty_print_str(cache, str, len, true);
522 84 }
523
524 #endif /* !MYSQL_SERVER */
525
526 #if defined(MYSQL_SERVER)
527
528 1134786 static void clear_all_errors(THD *thd, Relay_log_info *rli) {
529 1134786 thd->is_slave_error = false;
530 1134786 thd->clear_error();
531 1134860 rli->clear_error();
532
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 1134817 times.
1134877 if (rli->workers_array_initialized) {
533
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 60 times.
248 for (size_t i = 0; i < rli->get_worker_count(); i++) {
534 188 rli->get_worker(i)->clear_error();
535 }
536 }
537 1134877 }
538
539 395 inline int idempotent_error_code(int err_code) {
540 395 int ret = 0;
541
542
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
✓ Branch 2 taken 270 times.
395 switch (err_code) {
543 case 0:
544 ret = 1;
545 break;
546 /*
547 The following list of "idempotent" errors
548 means that an error from the list might happen
549 because of idempotent (more than once)
550 applying of a binlog file.
551 Notice, that binlog has a ddl operation its
552 second applying may cause
553
554 case HA_ERR_TABLE_DEF_CHANGED:
555 case HA_ERR_CANNOT_ADD_FOREIGN:
556
557 which are not included into to the list.
558
559 Note that HA_ERR_RECORD_DELETED is not in the list since
560 do_exec_row() should not return that error code.
561 */
562 125 case HA_ERR_RECORD_CHANGED:
563 case HA_ERR_KEY_NOT_FOUND:
564 case HA_ERR_END_OF_FILE:
565 case HA_ERR_FOUND_DUPP_KEY:
566 case HA_ERR_FOUND_DUPP_UNIQUE:
567 case HA_ERR_FOREIGN_DUPLICATE_KEY:
568 case HA_ERR_NO_REFERENCED_ROW:
569 case HA_ERR_ROW_IS_REFERENCED:
570 125 ret = 1;
571 125 break;
572 270 default:
573 270 ret = 0;
574 270 break;
575 }
576 395 return (ret);
577 }
578
579 /**
580 Ignore error code specified on command line.
581 */
582
583 569878 int ignored_error_code(int err_code) {
584
4/4
✓ Branch 0 taken 569261 times.
✓ Branch 1 taken 617 times.
✓ Branch 2 taken 417 times.
✓ Branch 3 taken 568844 times.
570295 return ((err_code == ER_SLAVE_IGNORED_TABLE) ||
585
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 274 times.
570295 (use_slave_mask && bitmap_is_set(&slave_error_mask, err_code)));
586 }
587
588 /*
589 This function converts an engine's error to a server error.
590
591 If the thread does not have an error already reported, it tries to
592 define it by calling the engine's method print_error. However, if a
593 mapping is not found, it uses the ER_UNKNOWN_ERROR and prints out a
594 warning message.
595 */
596 678 static int convert_handler_error(int error, THD *thd, TABLE *table) {
597
2/2
✓ Branch 0 taken 652 times.
✓ Branch 1 taken 26 times.
678 uint actual_error = (thd->is_error() ? thd->get_stmt_da()->mysql_errno() : 0);
598
599
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 652 times.
678 if (actual_error == 0) {
600 26 table->file->print_error(error, MYF(0));
601
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 actual_error = (thd->is_error() ? thd->get_stmt_da()->mysql_errno()
602 : ER_UNKNOWN_ERROR);
603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (actual_error == ER_UNKNOWN_ERROR)
604 LogErr(WARNING_LEVEL, ER_UNKNOWN_ERROR_DETECTED_IN_SE, error);
605 }
606
607 678 return (actual_error);
608 }
609
610 567048 inline bool concurrency_error_code(int error) {
611
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 567040 times.
567048 switch (error) {
612 8 case ER_LOCK_WAIT_TIMEOUT:
613 case ER_LOCK_DEADLOCK:
614 case ER_XA_RBDEADLOCK:
615 8 return true;
616 567040 default:
617 567040 return (false);
618 }
619 }
620
621 567389 inline bool unexpected_error_code(int unexpected_error) {
622
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 567384 times.
567389 switch (unexpected_error) {
623 5 case ER_NET_READ_ERROR:
624 case ER_NET_ERROR_ON_WRITE:
625 case ER_QUERY_INTERRUPTED:
626 case ER_SERVER_SHUTDOWN:
627 case ER_NEW_ABORTING_CONNECTION:
628 5 return (true);
629 567384 default:
630 567384 return (false);
631 }
632 }
633
634 /*
635 pretty_print_str()
636 */
637 20626 static void pretty_print_str(String *packet, const char *str, size_t len) {
638 20626 packet->append('\'');
639
640
2/2
✓ Branch 0 taken 342251 times.
✓ Branch 1 taken 20626 times.
362877 for (size_t i = 0; i < len; i++) {
641
8/8
✓ Branch 0 taken 4132 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2810 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2782 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 332513 times.
342251 switch (str[i]) {
642 4132 case '\n':
643
1/2
✓ Branch 0 taken 4132 times.
✗ Branch 1 not taken.
4132 packet->append("\\n");
644 4132 break;
645 2 case '\r':
646
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 packet->append("\\r");
647 2 break;
648 2810 case '\\':
649
1/2
✓ Branch 0 taken 2810 times.
✗ Branch 1 not taken.
2810 packet->append("\\\\");
650 2810 break;
651 2 case '\b':
652
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 packet->append("\\b");
653 2 break;
654 2782 case '\t':
655
1/2
✓ Branch 0 taken 2782 times.
✗ Branch 1 not taken.
2782 packet->append("\\t");
656 2782 break;
657 8 case '\'':
658
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 packet->append("\\'");
659 8 break;
660 2 case 0:
661
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 packet->append("\\0");
662 2 break;
663 332513 default:
664 332513 packet->append(str[i]);
665 332513 break;
666 }
667 }
668 20626 packet->append('\'');
669 20626 }
670
671 16504 static inline void pretty_print_str(String *packet, const String *str) {
672 16504 pretty_print_str(packet, str->ptr(), str->length());
673 16504 }
674
675 /**
676 Creates a temporary name for load data infile:.
677
678 @param buf Store new filename here
679 @param file_id File_id (part of file name)
680 @param event_server_id Event_id (part of file name)
681 @param ext Extension for file name
682
683 @return
684 Pointer to start of extension
685 */
686
687 193 static char *slave_load_file_stem(char *buf, uint file_id, int event_server_id,
688 const char *ext) {
689 char *res;
690 193 fn_format(buf, PREFIX_SQL_LOAD, replica_load_tmpdir, "", MY_UNPACK_FILENAME);
691 193 to_unix_path(buf);
692
693 193 buf = strend(buf);
694 193 int appended_length = sprintf(buf, "%s-%d-", server_uuid, event_server_id);
695 193 buf += appended_length;
696 193 res = longlong10_to_str(file_id, buf, 10);
697 193 my_stpcpy(res, ext); // Add extension last
698 193 return res; // Pointer to extension
699 }
700
701 /**
702 Delete all temporary files used for SQL_LOAD.
703 */
704
705 4077 static void cleanup_load_tmpdir() {
706 MY_DIR *dirp;
707 FILEINFO *file;
708 uint i;
709 char fname[FN_REFLEN], prefbuf[TEMP_FILE_MAX_LEN], *p;
710
711
2/4
✓ Branch 0 taken 4077 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4077 times.
4077 if (!(dirp = my_dir(replica_load_tmpdir, MYF(0)))) return;
712
713 /*
714 When we are deleting temporary files, we should only remove
715 the files associated with the server id of our server.
716 We don't use event_server_id here because since we've disabled
717 direct binlogging of Create_file/Append_file/Exec_load events
718 we cannot meet Start_log event in the middle of events from one
719 LOAD DATA.
720 */
721
1/2
✓ Branch 0 taken 4077 times.
✗ Branch 1 not taken.
4077 p = strmake(prefbuf, STRING_WITH_LEN(PREFIX_SQL_LOAD));
722 4077 sprintf(p, "%s-", server_uuid);
723
724
2/2
✓ Branch 0 taken 23883 times.
✓ Branch 1 taken 4077 times.
27960 for (i = 0; i < dirp->number_off_files; i++) {
725 23883 file = dirp->dir_entry + i;
726
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 23875 times.
23883 if (is_prefix(file->name, prefbuf)) {
727
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 fn_format(fname, file->name, replica_load_tmpdir, "", MY_UNPACK_FILENAME);
728
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 mysql_file_delete(key_file_misc, fname, MYF(0));
729 }
730 }
731
732
1/2
✓ Branch 0 taken 4077 times.
✗ Branch 1 not taken.
4077 my_dirend(dirp);
733 }
734 #endif
735
736 template <typename T>
737 45048 bool net_field_length_checked(const uchar **packet, size_t *max_length,
738 T *out) {
739
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 22464 times.
45048 if (*max_length < 1) return true;
740 44928 const uchar *pos = *packet;
741
2/2
✓ Branch 0 taken 22095 times.
✓ Branch 1 taken 369 times.
44928 if (*pos < 251) {
742 44190 (*packet)++;
743 44190 (*max_length)--;
744 44190 *out = (T)*pos;
745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 369 times.
738 } else if (*pos == 251) {
746 (*packet)++;
747 (*max_length)--;
748 *out = (T)NULL_LENGTH;
749
2/2
✓ Branch 0 taken 229 times.
✓ Branch 1 taken 140 times.
738 } else if (*pos == 252) {
750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 229 times.
458 if (*max_length < 3) return true;
751 458 (*packet) += 3;
752 458 (*max_length) -= 3;
753 458 *out = (T)uint2korr(pos + 1);
754
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 30 times.
280 } else if (*pos == 253) {
755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
220 if (*max_length < 4) return true;
756 220 (*packet) += 4;
757 220 (*max_length) -= 4;
758 220 *out = (T)uint3korr(pos + 1);
759 } else {
760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
60 if (*max_length < 9) return true;
761 60 (*packet) += 9;
762 60 (*max_length) -= 9;
763 60 *out = (T)uint8korr(pos + 1);
764 }
765 44928 return false;
766 }
767 template bool net_field_length_checked<size_t>(const uchar **packet,
768 size_t *max_length, size_t *out);
769 template bool net_field_length_checked<ulonglong>(const uchar **packet,
770 size_t *max_length,
771 ulonglong *out);
772
773 /**
774 Transforms a string into "" or its expression in 0x... form.
775 */
776
777 211 char *str_to_hex(char *to, const char *from, size_t len) {
778
2/2
✓ Branch 0 taken 208 times.
✓ Branch 1 taken 3 times.
211 if (len) {
779 208 *to++ = '0';
780 208 *to++ = 'x';
781 208 to = octet2hex(to, from, len);
782 } else
783 3 to = my_stpcpy(to, "\"\"");
784 211 return to; // pointer to end 0 of 'to'
785 }
786
787 #ifdef MYSQL_SERVER
788
789 /**
790 Append a version of the 'from' string suitable for use in a query to
791 the 'to' string. To generate a correct escaping, the character set
792 information in 'csinfo' is used.
793 */
794
795 128971 int append_query_string(const THD *thd, const CHARSET_INFO *csinfo,
796 String const *from, String *to) {
797 char *beg, *ptr;
798 128971 size_t const orig_len = to->length();
799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128971 times.
128972 if (to->reserve(orig_len + from->length() * 2 + 3)) return 1;
800
801 128971 beg = to->c_ptr_quick() + to->length();
802 128972 ptr = beg;
803
2/2
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 128798 times.
128972 if (csinfo->escape_with_backslash_is_dangerous)
804 174 ptr = str_to_hex(ptr, from->ptr(), from->length());
805 else {
806 128798 *ptr++ = '\'';
807
2/2
✓ Branch 0 taken 128119 times.
✓ Branch 1 taken 679 times.
128798 if (!(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)) {
808 128119 ptr +=
809 128119 escape_string_for_mysql(csinfo, ptr, 0, from->ptr(), from->length());
810 } else {
811 679 const char *frm_str = from->ptr();
812
813
2/2
✓ Branch 0 taken 30697 times.
✓ Branch 1 taken 679 times.
31376 for (; frm_str < (from->ptr() + from->length()); frm_str++) {
814 /* Using '' way to represent "'" */
815
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 30676 times.
30697 if (*frm_str == '\'') *ptr++ = *frm_str;
816
817 30697 *ptr++ = *frm_str;
818 }
819 }
820
821 128798 *ptr++ = '\'';
822 }
823 128972 to->length(orig_len + ptr - beg);
824 128972 return 0;
825 }
826 #endif
827
828 /**
829 Prints a "session_var=value" string. Used by mysqlbinlog to print some SET
830 commands just before it prints a query.
831 */
832
833 #ifndef MYSQL_SERVER
834
835 17620 static void print_set_option(IO_CACHE *file, uint32 bits_changed, uint32 option,
836 uint32 flags, const char *name, bool *need_comma) {
837
2/2
✓ Branch 0 taken 17606 times.
✓ Branch 1 taken 14 times.
17620 if (bits_changed & option) {
838
2/2
✓ Branch 0 taken 13201 times.
✓ Branch 1 taken 4405 times.
17606 if (*need_comma) my_b_printf(file, ", ");
839 17606 my_b_printf(file, "%s=%d", name, static_cast<bool>(flags & option));
840 17606 *need_comma = true;
841 }
842 17620 }
843 #endif
844
845 #ifdef MYSQL_SERVER
846 30684625 Replicated_columns_view::Replicated_columns_view(
847 30684625 Replicated_columns_view::enum_replication_flow direction, THD const *thd)
848 30684625 : Replicated_columns_view{nullptr, direction, thd} {}
849
850 265343370 Replicated_columns_view::Replicated_columns_view(
851 TABLE const *target,
852 265343370 Replicated_columns_view::enum_replication_flow direction, THD const *thd)
853 265343370 : Table_columns_view{} {
854 265444511 filter_fn_type filter{nullptr};
855
856
2/2
✓ Branch 0 taken 233415938 times.
✓ Branch 1 taken 32007292 times.
265423230 if (direction == Replicated_columns_view::OUTBOUND)
857 688488557 filter = [this](TABLE const *table, size_t column_index) -> bool {
858 688488557 return this->outbound_filtering(table, column_index);
859 233415938 };
860 else
861 3885165 filter = [this](TABLE const *table, size_t column_index) -> bool {
862 3885165 return this->inbound_filtering(table, column_index);
863 32007292 };
864
865
1/2
✓ Branch 0 taken 265379260 times.
✗ Branch 1 not taken.
265446533 this->set_thd(thd) //
866
2/4
✓ Branch 0 taken 265350362 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 265444453 times.
✗ Branch 3 not taken.
530822982 .set_filter(filter) //
867
1/2
✓ Branch 0 taken 265443722 times.
✗ Branch 1 not taken.
265444453 .set_table(target);
868 265427076 }
869
870 265649988 Replicated_columns_view &Replicated_columns_view::set_thd(THD const *thd) {
871 265649988 this->m_thd = thd;
872 265649988 this->init_fields_bitmaps();
873 265669301 return (*this);
874 }
875
876 3885111 bool Replicated_columns_view::is_inbound_filtering_enabled() {
877 7770235 return (this->m_thd == nullptr ||
878
2/2
✓ Branch 0 taken 3884780 times.
✓ Branch 1 taken 344 times.
3885124 this->m_thd->variables.immediate_server_version ==
879
1/2
✓ Branch 0 taken 3885124 times.
✗ Branch 1 not taken.
7770235 UNDEFINED_SERVER_VERSION ||
880
2/2
✓ Branch 0 taken 3884771 times.
✓ Branch 1 taken 9 times.
7769891 this->m_thd->variables.immediate_server_version >= 80018);
881 }
882
883 3885096 bool Replicated_columns_view::inbound_filtering(TABLE const *table,
884 size_t column_index) {
885
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3885157 times.
3885096 if (!this->is_inbound_filtering_enabled()) return false;
886 // If the set of filtered columns is changed, we need to replicate the change
887 // in other blocks that reproduce the behavior - Rapid binlog parser, for
888 // instance.
889 3885157 return bitmap_is_set(&table->fields_for_functional_indexes, column_index);
890 }
891
892 688445447 bool Replicated_columns_view::outbound_filtering(TABLE const *table,
893 size_t column_index) {
894 // If the set of filtered columns is changed, we need to replicate the change
895 // in other blocks that reproduce the behavior - Rapid binlog parser, for
896 // instance.
897 688445447 return bitmap_is_set(&table->fields_for_functional_indexes, column_index);
898 }
899 #endif
900
901 /**************************************************************************
902 Log_event methods (= the parent class of all events)
903 **************************************************************************/
904
905 #ifdef MYSQL_SERVER
906
907 54679759 time_t Log_event::get_time() {
908 /* Not previously initialized */
909
3/4
✓ Branch 0 taken 286871 times.
✓ Branch 1 taken 54392888 times.
✓ Branch 2 taken 286871 times.
✗ Branch 3 not taken.
54679759 if (!common_header->when.tv_sec && !common_header->when.tv_usec) {
910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 286871 times.
286871 THD *tmp_thd = thd ? thd : current_thd;
911
2/2
✓ Branch 0 taken 248334 times.
✓ Branch 1 taken 38537 times.
286871 if (tmp_thd)
912 248334 common_header->when = tmp_thd->start_time;
913 else
914 38537 my_micro_time_to_timeval(my_micro_time(), &(common_header->when));
915 }
916 54680038 return (time_t)common_header->when.tv_sec;
917 }
918
919 #endif
920
921 /**
922 @return
923 returns the human readable name of the event's type
924 */
925
926 286500 const char *Log_event::get_type_str(Log_event_type type) {
927
28/33
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 121333 times.
✓ Branch 2 taken 1730 times.
✓ Branch 3 taken 22092 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 8121 times.
✓ Branch 8 taken 62 times.
✓ Branch 9 taken 4752 times.
✓ Branch 10 taken 34921 times.
✓ Branch 11 taken 14 times.
✓ Branch 12 taken 3 times.
✓ Branch 13 taken 5 times.
✓ Branch 14 taken 40 times.
✓ Branch 15 taken 34 times.
✓ Branch 16 taken 9 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 45 times.
✓ Branch 19 taken 57546 times.
✓ Branch 20 taken 3033 times.
✓ Branch 21 taken 2682 times.
✓ Branch 22 taken 4688 times.
✓ Branch 23 taken 18635 times.
✓ Branch 24 taken 3888 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 224 times.
✓ Branch 28 taken 100 times.
✓ Branch 29 taken 2492 times.
✓ Branch 30 taken 37 times.
✓ Branch 31 taken 3 times.
✗ Branch 32 not taken.
286500 switch (type) {
928 6 case binary_log::STOP_EVENT:
929 6 return "Stop";
930 121333 case binary_log::QUERY_EVENT:
931 121333 return "Query";
932 1730 case binary_log::ROTATE_EVENT:
933 1730 return "Rotate";
934 22092 case binary_log::INTVAR_EVENT:
935 22092 return "Intvar";
936 4 case binary_log::APPEND_BLOCK_EVENT:
937 4 return "Append_block";
938 case binary_log::DELETE_FILE_EVENT:
939 return "Delete_file";
940 1 case binary_log::RAND_EVENT:
941 1 return "RAND";
942 8121 case binary_log::XID_EVENT:
943 8121 return "Xid";
944 62 case binary_log::USER_VAR_EVENT:
945 62 return "User var";
946 4752 case binary_log::FORMAT_DESCRIPTION_EVENT:
947 4752 return "Format_desc";
948 34921 case binary_log::TABLE_MAP_EVENT:
949 34921 return "Table_map";
950 14 case binary_log::WRITE_ROWS_EVENT_V1:
951 14 return "Write_rows_v1";
952 3 case binary_log::UPDATE_ROWS_EVENT_V1:
953 3 return "Update_rows_v1";
954 5 case binary_log::DELETE_ROWS_EVENT_V1:
955 5 return "Delete_rows_v1";
956 40 case binary_log::BEGIN_LOAD_QUERY_EVENT:
957 40 return "Begin_load_query";
958 34 case binary_log::EXECUTE_LOAD_QUERY_EVENT:
959 34 return "Execute_load_query";
960 9 case binary_log::INCIDENT_EVENT:
961 9 return "Incident";
962 case binary_log::IGNORABLE_LOG_EVENT:
963 return "Ignorable";
964 45 case binary_log::ROWS_QUERY_LOG_EVENT:
965 45 return "Rows_query";
966 57546 case binary_log::WRITE_ROWS_EVENT:
967 57546 return "Write_rows";
968 3033 case binary_log::UPDATE_ROWS_EVENT:
969 3033 return "Update_rows";
970 2682 case binary_log::DELETE_ROWS_EVENT:
971 2682 return "Delete_rows";
972 4688 case binary_log::GTID_LOG_EVENT:
973 4688 return "Gtid";
974 18635 case binary_log::ANONYMOUS_GTID_LOG_EVENT:
975 18635 return "Anonymous_Gtid";
976 3888 case binary_log::PREVIOUS_GTIDS_LOG_EVENT:
977 3888 return "Previous_gtids";
978 case binary_log::HEARTBEAT_LOG_EVENT:
979 case binary_log::HEARTBEAT_LOG_EVENT_V2:
980 return "Heartbeat";
981 case binary_log::TRANSACTION_CONTEXT_EVENT:
982 return "Transaction_context";
983 224 case binary_log::VIEW_CHANGE_EVENT:
984 224 return "View_change";
985 100 case binary_log::XA_PREPARE_LOG_EVENT:
986 100 return "XA_prepare";
987 2492 case binary_log::PARTIAL_UPDATE_ROWS_EVENT:
988 2492 return "Update_rows_partial";
989 37 case binary_log::TRANSACTION_PAYLOAD_EVENT:
990 37 return "Transaction_payload";
991 3 case binary_log::START_5_7_ENCRYPTION_EVENT:
992 3 return "Start_5_7_encryption";
993 default:
994 return "Unknown"; /* impossible */
995 }
996 }
997
998 286499 const char *Log_event::get_type_str() const {
999 286499 return get_type_str(get_type_code());
1000 }
1001
1002 /*
1003 Log_event::Log_event()
1004 */
1005
1006 #ifdef MYSQL_SERVER
1007 54465286 Log_event::Log_event(THD *thd_arg, uint16 flags_arg,
1008 enum_event_cache_type cache_type_arg,
1009 enum_event_logging_type logging_type_arg,
1010 54465286 Log_event_header *header, Log_event_footer *footer)
1011 54465286 : temp_buf(nullptr),
1012 54465286 m_free_temp_buf_in_destructor(true),
1013 54465286 exec_time(0),
1014 54465286 event_cache_type(cache_type_arg),
1015 54465286 event_logging_type(logging_type_arg),
1016 54465286 crc(0),
1017 54465286 common_header(header),
1018 54465286 common_footer(footer),
1019 54465286 thd(thd_arg) {
1020 54465286 server_id = thd->server_id;
1021 54465286 common_header->unmasked_server_id = server_id;
1022 54465286 common_header->when = thd->start_time;
1023 54465286 common_header->log_pos = 0;
1024 54465286 common_header->flags = flags_arg;
1025 54465286 }
1026
1027 /**
1028 This minimal constructor is for when you are not even sure that there
1029 is a valid THD. For example in the server when we are shutting down or
1030 flushing logs after receiving a SIGHUP (then we must write a Rotate to
1031 the binlog but we have no THD, so we need this minimal constructor).
1032 */
1033
1034 370712 Log_event::Log_event(Log_event_header *header, Log_event_footer *footer,
1035 enum_event_cache_type cache_type_arg,
1036 370712 enum_event_logging_type logging_type_arg)
1037 370712 : temp_buf(nullptr),
1038 370712 m_free_temp_buf_in_destructor(true),
1039 370712 exec_time(0),
1040 370712 event_cache_type(cache_type_arg),
1041 370712 event_logging_type(logging_type_arg),
1042 370712 crc(0),
1043 370712 common_header(header),
1044 370712 common_footer(footer),
1045 370712 thd(nullptr) {
1046 370712 server_id = ::server_id;
1047 370712 common_header->unmasked_server_id = server_id;
1048 370712 }
1049 #endif /* MYSQL_SERVER */
1050
1051 /*
1052 Log_event::Log_event()
1053 */
1054
1055 41833401 Log_event::Log_event(Log_event_header *header, Log_event_footer *footer)
1056 41833401 : temp_buf(nullptr),
1057 41833401 m_free_temp_buf_in_destructor(true),
1058 41833401 exec_time(0),
1059 41833401 event_cache_type(EVENT_INVALID_CACHE),
1060 41833401 event_logging_type(EVENT_INVALID_LOGGING),
1061 41833401 crc(0),
1062 41833401 common_header(header),
1063 41833401 common_footer(footer) {
1064 #ifdef MYSQL_SERVER
1065 41621333 thd = nullptr;
1066 #endif
1067 /*
1068 Mask out any irrelevant parts of the server_id
1069 */
1070 41833401 server_id = common_header->unmasked_server_id & opt_server_id_mask;
1071 41833401 }
1072
1073 /*
1074 This method is not on header file to avoid using key_memory_log_event
1075 outside log_event.cc, allowing header file to be included on plugins.
1076 */
1077 67562398 void *Log_event::operator new(size_t size) {
1078 67562398 return my_malloc(key_memory_log_event, size, MYF(MY_WME | MY_FAE));
1079 }
1080
1081 #ifdef MYSQL_SERVER
1082 1531622 inline int Log_event::do_apply_event_worker(Slave_worker *w) {
1083
4/4
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 1531610 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 52 times.
1531622 DBUG_EXECUTE_IF("crash_in_a_worker", {
1084 /* we will crash a worker after waiting for
1085 2 seconds to make sure that other transactions are
1086 scheduled and completed */
1087 if (w->id == 2) {
1088 DBUG_SET("-d,crash_in_a_worker");
1089 my_sleep(2000000);
1090 DBUG_SUICIDE();
1091 }
1092 });
1093 1531662 return do_apply_event(w);
1094 }
1095
1096 14914 int Log_event::do_update_pos(Relay_log_info *rli) {
1097 14914 int error = 0;
1098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14914 times.
14914 assert(!rli->belongs_to_client());
1099
1100
1/2
✓ Branch 0 taken 14914 times.
✗ Branch 1 not taken.
14914 if (rli) error = rli->stmt_done(common_header->log_pos);
1101 14914 return error;
1102 }
1103
1104 1779189 Log_event::enum_skip_reason Log_event::do_shall_skip(Relay_log_info *rli) {
1105 /*
1106 The logic for slave_skip_counter is as follows:
1107
1108 - Events that are skipped because they have the same server_id as
1109 the slave do not decrease slave_skip_counter.
1110
1111 - Other events (that pass the server_id test) will decrease
1112 slave_skip_counter.
1113
1114 - Except in one case: if slave_skip_counter==1, it will only
1115 decrease to 0 if we are at a so-called group boundary. Here, a
1116 group is defined as the range of events that represent a single
1117 transaction in the relay log: see comment for is_in_group in
1118 rpl_rli.h for a definition.
1119
1120 The difficult part to implement is the logic to avoid decreasing
1121 the counter to 0. Given that groups have the form described in
1122 is_in_group in rpl_rli.h, we implement the logic as follows:
1123
1124 - Gtid, Rand, User_var, Int_var will never decrease the counter to
1125 0.
1126
1127 - BEGIN will set thd->variables.option_bits & OPTION_BEGIN and
1128 COMMIT/Xid will clear it. This happens regardless of whether
1129 the BEGIN/COMMIT/Xid is skipped itself.
1130
1131 - Other events will decrease the counter unless OPTION_BEGIN is
1132 set.
1133 */
1134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1779189 times.
1779189 DBUG_PRINT("info", ("ev->server_id=%lu, ::server_id=%lu,"
1135 " rli->replicate_same_server_id=%d,"
1136 " rli->slave_skip_counter=%d",
1137 (ulong)server_id, (ulong)::server_id,
1138 rli->replicate_same_server_id, rli->slave_skip_counter));
1139
6/6
✓ Branch 0 taken 39231 times.
✓ Branch 1 taken 1739958 times.
✓ Branch 2 taken 21217 times.
✓ Branch 3 taken 18014 times.
✓ Branch 4 taken 18347 times.
✓ Branch 5 taken 1760842 times.
3540364 if ((server_id == ::server_id && !rli->replicate_same_server_id) ||
1140
4/4
✓ Branch 0 taken 353 times.
✓ Branch 1 taken 1760822 times.
✓ Branch 2 taken 333 times.
✓ Branch 3 taken 20 times.
1761175 (rli->slave_skip_counter == 1 && rli->is_in_group()))
1141 18347 return EVENT_SKIP_IGNORE;
1142
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 1760680 times.
1760842 else if (rli->slave_skip_counter > 0)
1143 162 return EVENT_SKIP_COUNT;
1144 else
1145 1760680 return EVENT_SKIP_NOT;
1146 }
1147
1148 /*
1149 Log_event::pack_info()
1150 */
1151
1152 9 int Log_event::pack_info(Protocol *protocol) {
1153 9 protocol->store("", &my_charset_bin);
1154 9 return 0;
1155 }
1156
1157
1/2
✓ Branch 0 taken 5248 times.
✗ Branch 1 not taken.
5248 const char *Log_event::get_db() { return thd ? thd->db().str : nullptr; }
1158
1159 /**
1160 Only called by SHOW BINLOG EVENTS
1161 */
1162 200877 int Log_event::net_send(Protocol *protocol, const char *log_name,
1163 my_off_t pos) {
1164 200877 const char *p = strrchr(log_name, FN_LIBCHAR);
1165 const char *event_type;
1166
2/2
✓ Branch 0 taken 200865 times.
✓ Branch 1 taken 12 times.
200877 if (p) log_name = p + 1;
1167
1168 200877 protocol->start_row();
1169 200877 protocol->store(log_name, &my_charset_bin);
1170 200877 protocol->store((ulonglong)pos);
1171 200877 event_type = get_type_str();
1172 200877 protocol->store_string(event_type, strlen(event_type), &my_charset_bin);
1173 200877 protocol->store((uint32)server_id);
1174 200877 protocol->store((ulonglong)common_header->log_pos);
1175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200877 times.
200877 if (pack_info(protocol)) return 1;
1176 200877 return protocol->end_row();
1177 }
1178
1179 /**
1180 init_show_field_list() prepares the column names and types for the
1181 output of SHOW BINLOG EVENTS; it is used only by SHOW BINLOG
1182 EVENTS.
1183 */
1184
1185 18099 void Log_event::init_show_field_list(mem_root_deque<Item *> *field_list) {
1186
3/6
✓ Branch 0 taken 18099 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18099 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18099 times.
✗ Branch 5 not taken.
18099 field_list->push_back(new Item_empty_string("Log_name", 20));
1187
2/4
✓ Branch 0 taken 18099 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18099 times.
✗ Branch 3 not taken.
36198 field_list->push_back(new Item_return_int("Pos", MY_INT32_NUM_DECIMAL_DIGITS,
1188
1/2
✓ Branch 0 taken 18099 times.
✗ Branch 1 not taken.
36198 MYSQL_TYPE_LONGLONG));
1189
3/6
✓ Branch 0 taken 18099 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18099 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18099 times.
✗ Branch 5 not taken.
18099 field_list->push_back(new Item_empty_string("Event_type", 20));
1190
3/6
✓ Branch 0 taken 18099 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18099 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18099 times.
✗ Branch 5 not taken.
18099 field_list->push_back(new Item_return_int("Server_id", 10, MYSQL_TYPE_LONG));
1191
2/4
✓ Branch 0 taken 18099 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18099 times.
✗ Branch 3 not taken.
36198 field_list->push_back(new Item_return_int(
1192
1/2
✓ Branch 0 taken 18099 times.
✗ Branch 1 not taken.
36198 "End_log_pos", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG));
1193
3/6
✓ Branch 0 taken 18099 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18099 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18099 times.
✗ Branch 5 not taken.
18099 field_list->push_back(new Item_empty_string("Info", 20));
1194 18099 }
1195
1196 /**
1197 A decider of whether to trigger checksum computation or not.
1198 To be invoked in Log_event::write() stack.
1199 The decision is positive
1200
1201 S,M) if it's been marked for checksumming with @c checksum_alg
1202
1203 M) otherwise, if @@global.binlog_checksum is not NONE and the event is
1204 directly written to the binlog file.
1205 The to-be-cached event decides at @c write_cache() time.
1206
1207 Otherwise the decision is negative.
1208
1209 @note A side effect of the method is altering Log_event::checksum_alg
1210 it the latter was undefined at calling.
1211
1212 @return true (positive) or false (negative)
1213 */
1214 441068615 bool Log_event::need_checksum() {
1215
1/2
✓ Branch 0 taken 441078037 times.
✗ Branch 1 not taken.
441068615 DBUG_TRACE;
1216 441078037 bool ret = false;
1217 /*
1218 few callers of Log_event::write
1219 (incl FD::write, FD constructing code on the slave side, Rotate relay log
1220 and Stop event)
1221 provides their checksum alg preference through Log_event::checksum_alg.
1222 */
1223
2/2
✓ Branch 0 taken 386692785 times.
✓ Branch 1 taken 54385252 times.
441078037 if (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF)
1224 386692785 ret = (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF);
1225
1/2
✓ Branch 0 taken 54386426 times.
✗ Branch 1 not taken.
54385252 else if (binlog_checksum_options != binary_log::BINLOG_CHECKSUM_ALG_OFF &&
1226
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 54386417 times.
54386426 event_cache_type == Log_event::EVENT_NO_CACHE)
1227 9 ret = (binlog_checksum_options != 0);
1228 else
1229 54385243 ret = false;
1230
1231 /*
1232 FD calls the methods before data_written has been calculated.
1233 The following invariant claims if the current is not the first
1234 call (and therefore data_written is not zero) then `ret' must be
1235 true. It may not be null because FD is always checksummed.
1236 */
1237
1238
5/6
✓ Branch 0 taken 449950 times.
✓ Branch 1 taken 440628130 times.
✓ Branch 2 taken 11075 times.
✓ Branch 3 taken 438875 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11075 times.
441078037 assert(get_type_code() != binary_log::FORMAT_DESCRIPTION_EVENT || ret ||
1239 common_header->data_written == 0);
1240
1241
2/2
✓ Branch 0 taken 54386703 times.
✓ Branch 1 taken 386691377 times.
441078080 if (common_footer->checksum_alg == binary_log::BINLOG_CHECKSUM_ALG_UNDEF)
1242 54386703 common_footer->checksum_alg =
1243
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 54386694 times.
54386703 ret ? // calculated value stored
1244 9 static_cast<enum_binlog_checksum_alg>(binlog_checksum_options)
1245 : binary_log::BINLOG_CHECKSUM_ALG_OFF;
1246
1247
15/18
✓ Branch 0 taken 1045162 times.
✓ Branch 1 taken 440032918 times.
✓ Branch 2 taken 1060 times.
✓ Branch 3 taken 1044102 times.
✓ Branch 4 taken 1054 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 979 times.
✓ Branch 7 taken 75 times.
✓ Branch 8 taken 979 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 907 times.
✓ Branch 11 taken 72 times.
✓ Branch 12 taken 16 times.
✓ Branch 13 taken 891 times.
✓ Branch 14 taken 16 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1045162 times.
✗ Branch 17 not taken.
441078080 assert(
1248 !ret ||
1249 ((common_footer->checksum_alg ==
1250 static_cast<enum_binlog_checksum_alg>(binlog_checksum_options) ||
1251 /*
1252 Stop event closes the relay-log and its checksum alg
1253 preference is set by the caller can be different
1254 from the server's binlog_checksum_options.
1255 */
1256 get_type_code() == binary_log::STOP_EVENT ||
1257 /*
1258 Rotate:s can be checksummed regardless of the server's
1259 binlog_checksum_options. That applies to both
1260 the local RL's Rotate and the master's Rotate
1261 which IO thread instantiates via queue_binlog_ver_3_event.
1262 */
1263 get_type_code() == binary_log::ROTATE_EVENT ||
1264 get_type_code() == binary_log::START_5_7_ENCRYPTION_EVENT ||
1265 /*
1266 The previous event has its checksum option defined
1267 according to the format description event.
1268 */
1269 get_type_code() == binary_log::PREVIOUS_GTIDS_LOG_EVENT ||
1270 /* FD is always checksummed */
1271 get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT ||
1272 /*
1273 View_change_log_event is queued into relay log by the
1274 local member, which may have a different checksum algorithm
1275 than the one of the event source.
1276 */
1277 get_type_code() == binary_log::VIEW_CHANGE_EVENT) &&
1278 common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF));
1279
1280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 441078080 times.
441078080 assert(common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
1281
5/8
✓ Branch 0 taken 440847626 times.
✓ Branch 1 taken 230027 times.
✓ Branch 2 taken 440789746 times.
✓ Branch 3 taken 55571 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 285919 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
441078080 assert(((get_type_code() != binary_log::ROTATE_EVENT &&
1282 get_type_code() != binary_log::STOP_EVENT) ||
1283 get_type_code() != binary_log::FORMAT_DESCRIPTION_EVENT) ||
1284 event_cache_type == Log_event::EVENT_NO_CACHE);
1285
1286 441078909 return ret;
1287 441075665 }
1288
1289 279652339 bool Log_event::wrapper_my_b_safe_write(Basic_ostream *ostream,
1290 const uchar *buf, size_t size) {
1291
2/2
✓ Branch 0 taken 2550002 times.
✓ Branch 1 taken 277102337 times.
279652339 if (size == 0) return false;
1292
1293
5/6
✓ Branch 0 taken 270562 times.
✓ Branch 1 taken 276835999 times.
✓ Branch 2 taken 270562 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 270562 times.
✓ Branch 5 taken 276835999 times.
277102337 if (need_checksum() && size != 0) crc = checksum_crc32(crc, buf, size);
1294
1295 277106561 return ostream->write(buf, size);
1296 }
1297
1298 54628732 bool Log_event::write_footer(Basic_ostream *ostream) {
1299 /*
1300 footer contains the checksum-algorithm descriptor
1301 followed by the checksum value
1302 */
1303
2/2
✓ Branch 0 taken 231875 times.
✓ Branch 1 taken 54397014 times.
54628732 if (need_checksum()) {
1304 uchar buf[BINLOG_CHECKSUM_LEN];
1305 231875 int4store(buf, crc);
1306
1/2
✓ Branch 0 taken 231887 times.
✗ Branch 1 not taken.
231887 return ostream->write((uchar *)buf, sizeof(buf));
1307 }
1308 54397014 return false;
1309 }
1310
1311 54628148 uint32 Log_event::write_header_to_memory(uchar *buf) {
1312 // Query start time
1313 54628148 ulong timestamp = (ulong)get_time();
1314
1315 #ifndef NDEBUG
1316
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 54628047 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54628047 times.
54628261 if (DBUG_EVALUATE_IF("inc_event_time_by_1_hour", 1, 0) &&
1317 DBUG_EVALUATE_IF("dec_event_time_by_1_hour", 1, 0)) {
1318 /**
1319 This assertion guarantees that these debug flags are not
1320 used at the same time (they would cancel each other).
1321 */
1322 assert(0);
1323 } else {
1324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54627897 times.
54628047 DBUG_EXECUTE_IF("inc_event_time_by_1_hour", timestamp = timestamp + 3600;);
1325
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 54628174 times.
54627897 DBUG_EXECUTE_IF("dec_event_time_by_1_hour", timestamp = timestamp - 3600;);
1326 }
1327 #endif
1328
1329 /*
1330 Header will be of size LOG_EVENT_HEADER_LEN for all events, except for
1331 FORMAT_DESCRIPTION_EVENT and ROTATE_EVENT, where it will be
1332 LOG_EVENT_MINIMAL_HEADER_LEN (remember these 2 have a frozen header,
1333 because we read them before knowing the format).
1334 */
1335
1336 54628180 int4store(buf, timestamp);
1337 54628050 buf[EVENT_TYPE_OFFSET] = get_type_code();
1338 54628003 int4store(buf + SERVER_ID_OFFSET, server_id);
1339 54628227 int4store(buf + EVENT_LEN_OFFSET,
1340 54628227 static_cast<uint32>(common_header->data_written));
1341 54628333 int4store(buf + LOG_POS_OFFSET, static_cast<uint32>(common_header->log_pos));
1342 54628543 int2store(buf + FLAGS_OFFSET, common_header->flags);
1343
1344 54628761 return LOG_EVENT_HEADER_LEN;
1345 }
1346
1347 54626625 bool Log_event::write_header(Basic_ostream *ostream, size_t event_data_length) {
1348 uchar header[LOG_EVENT_HEADER_LEN];
1349 bool ret;
1350
1/2
✓ Branch 0 taken 54628459 times.
✗ Branch 1 not taken.
54626625 DBUG_TRACE;
1351
1352 /* Store number of bytes that will be written by this event */
1353 54628459 common_header->data_written = event_data_length + sizeof(header);
1354
1355
3/4
✓ Branch 0 taken 54628489 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 231899 times.
✓ Branch 3 taken 54396590 times.
54628459 if (need_checksum()) {
1356
1/2
✓ Branch 0 taken 231899 times.
✗ Branch 1 not taken.
231899 crc = checksum_crc32(0L, nullptr, 0);
1357 231899 common_header->data_written += BINLOG_CHECKSUM_LEN;
1358 }
1359
1360 /*
1361 Usually events are written into binlog cache first. And later, they are
1362 flushed into binlog file. When events are being written into binlog cache,
1363 log_pos(a.k.a. end_log_pos) field is meaningless. So it is set to 0. the
1364 log_pos field will be updated later when the events are being flushed into
1365 binlog file.
1366
1367 In a few cases(e.g. rotation(FD, Rotate events)), events are written into
1368 binlog file directly through event->write(). In these cases, log_pos is
1369 updated to the begin position of the event before calling event->write().
1370 Then log_pos is updated to the end position of the event here.
1371 */
1372
2/2
✓ Branch 0 taken 224016 times.
✓ Branch 1 taken 54404473 times.
54628489 if (common_header->log_pos != 0) {
1373 224016 common_header->log_pos += common_header->data_written;
1374 }
1375
1376
1/2
✓ Branch 0 taken 54628806 times.
✗ Branch 1 not taken.
54628489 write_header_to_memory(header);
1377
1378
1/2
✓ Branch 0 taken 54627546 times.
✗ Branch 1 not taken.
54628806 ret = ostream->write(header, LOG_EVENT_HEADER_LEN);
1379
1380 /*
1381 Update the checksum.
1382
1383 In case this is a Format_description_log_event, we need to clear
1384 the LOG_EVENT_BINLOG_IN_USE_F flag before computing the checksum,
1385 since the flag will be cleared when the binlog is closed. On
1386 verification, the flag is dropped before computing the checksum
1387 too.
1388 */
1389
5/6
✓ Branch 0 taken 54628858 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 231899 times.
✓ Branch 3 taken 54396959 times.
✓ Branch 4 taken 30662 times.
✓ Branch 5 taken 54598196 times.
54859445 if (need_checksum() &&
1390
2/2
✓ Branch 0 taken 30662 times.
✓ Branch 1 taken 201237 times.
231899 (common_header->flags & LOG_EVENT_BINLOG_IN_USE_F) != 0) {
1391 30662 common_header->flags &= ~LOG_EVENT_BINLOG_IN_USE_F;
1392 30662 int2store(header + FLAGS_OFFSET, common_header->flags);
1393 }
1394
1/2
✓ Branch 0 taken 54629459 times.
✗ Branch 1 not taken.
54628858 crc = my_checksum(crc, header, LOG_EVENT_HEADER_LEN);
1395
1396 54628830 return ret;
1397 54629459 }
1398 #endif /* MYSQL_SERVER */
1399
1400 158170114 bool Log_event::is_valid() {
1401
3/4
✓ Branch 0 taken 158195541 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 157753584 times.
✓ Branch 3 taken 438205 times.
158170114 return common_header != nullptr && common_header->get_is_valid();
1402 }
1403
1404 #ifndef MYSQL_SERVER
1405
1406 /*
1407 Log_event::print_header()
1408 */
1409
1410 181709 void Log_event::print_header(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info,
1411 bool is_more [[maybe_unused]]) const {
1412 [[maybe_unused]] int write_res;
1413 char llbuff[22];
1414 181709 my_off_t hexdump_from = print_event_info->hexdump_from;
1415
1/2
✓ Branch 0 taken 181709 times.
✗ Branch 1 not taken.
181709 DBUG_TRACE;
1416
1417
1/2
✓ Branch 0 taken 181709 times.
✗ Branch 1 not taken.
181709 my_b_printf(file, "#");
1418
1/2
✓ Branch 0 taken 181709 times.
✗ Branch 1 not taken.
181709 print_timestamp(file, nullptr);
1419
1/2
✓ Branch 0 taken 181709 times.
✗ Branch 1 not taken.
181709 my_b_printf(file, " server id %lu end_log_pos %s ", (ulong)server_id,
1420
1/2
✓ Branch 0 taken 181709 times.
✗ Branch 1 not taken.
181709 llstr(common_header->log_pos, llbuff));
1421
1422 /* print the checksum */
1423
1424
2/2
✓ Branch 0 taken 181027 times.
✓ Branch 1 taken 682 times.
181709 if (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF &&
1425
2/2
✓ Branch 0 taken 180092 times.
✓ Branch 1 taken 935 times.
181027 common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF) {
1426 char checksum_buf[BINLOG_CHECKSUM_LEN * 2 + 4]; // to fit to "0x%lx "
1427 size_t const bytes_written =
1428 180092 snprintf(checksum_buf, sizeof(checksum_buf), "0x%08lx ", (ulong)crc);
1429
1/2
✓ Branch 0 taken 180092 times.
✗ Branch 1 not taken.
180092 my_b_printf(
1430 file, "%s ",
1431
1/2
✓ Branch 0 taken 180092 times.
✗ Branch 1 not taken.
180092 get_type(&binlog_checksum_typelib, common_footer->checksum_alg));
1432
1/2
✓ Branch 0 taken 180092 times.
✗ Branch 1 not taken.
180092 my_b_printf(file, checksum_buf, bytes_written);
1433 }
1434
1435 /* mysqlbinlog --hexdump */
1436
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 181373 times.
181709 if (print_event_info->hexdump_from) {
1437
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 my_b_printf(file, "\n");
1438 336 uchar *ptr = (uchar *)temp_buf;
1439 my_off_t size =
1440 336 uint4korr(ptr + EVENT_LEN_OFFSET) - LOG_EVENT_MINIMAL_HEADER_LEN;
1441 my_off_t i;
1442
1443 /* Header len * 4 >= header len * (2 chars + space + extra space) */
1444 336 char *h, hex_string[49] = {0};
1445 336 char *c, char_string[16 + 1] = {0};
1446
1447 /* Pretty-print event common header if header is exactly 19 bytes */
1448
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 if (print_event_info->common_header_len == LOG_EVENT_MINIMAL_HEADER_LEN) {
1449 char emit_buf[256]; // Enough for storing one line
1450
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 my_b_printf(file,
1451 "# Position Timestamp Type Master ID "
1452 "Size Master Pos Flags \n");
1453 336 size_t const bytes_written = snprintf(
1454 emit_buf, sizeof(emit_buf),
1455 "# %8.8lx %02x %02x %02x %02x %02x "
1456 "%02x %02x %02x %02x %02x %02x %02x %02x "
1457 "%02x %02x %02x %02x %02x %02x\n",
1458 336 (unsigned long)hexdump_from, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4],
1459 336 ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12],
1460 336 ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]);
1461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
336 assert(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1462
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 write_res = my_b_write(file, (uchar *)emit_buf, bytes_written);
1463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
336 assert(write_res == 0);
1464 336 ptr += LOG_EVENT_MINIMAL_HEADER_LEN;
1465 336 hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN;
1466 }
1467
1468 /* Rest of event (without common header) */
1469
2/2
✓ Branch 0 taken 424941 times.
✓ Branch 1 taken 336 times.
425277 for (i = 0, c = char_string, h = hex_string; i < size; i++, ptr++) {
1470
2/2
✓ Branch 0 taken 213196 times.
✓ Branch 1 taken 211745 times.
424941 snprintf(h, 4, (i % 16 <= 7) ? "%02x " : " %02x", *ptr);
1471 424941 h += 3;
1472
1473
2/2
✓ Branch 0 taken 319143 times.
✓ Branch 1 taken 105798 times.
424941 *c++ = my_isalnum(&my_charset_bin, *ptr) ? *ptr : '.';
1474
1475
2/2
✓ Branch 0 taken 26367 times.
✓ Branch 1 taken 398574 times.
424941 if (i % 16 == 15) {
1476 /*
1477 my_b_printf() does not support full printf() formats, so we
1478 have to do it this way.
1479
1480 TODO: Rewrite my_b_printf() to support full printf() syntax.
1481 */
1482 char emit_buf[256];
1483 size_t const bytes_written =
1484 26367 snprintf(emit_buf, sizeof(emit_buf), "# %8.8lx %-48.48s |%16s|\n",
1485 26367 (unsigned long)(hexdump_from + (i & 0xfffffff0)),
1486 26367 hex_string, char_string);
1487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26367 times.
26367 assert(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1488
1/2
✓ Branch 0 taken 26367 times.
✗ Branch 1 not taken.
26367 write_res = my_b_write(file, (uchar *)emit_buf, bytes_written);
1489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26367 times.
26367 assert(write_res == 0);
1490 26367 hex_string[0] = 0;
1491 26367 char_string[0] = 0;
1492 26367 c = char_string;
1493 26367 h = hex_string;
1494 }
1495 }
1496 336 *c = '\0';
1497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
336 assert(hex_string[48] == 0);
1498
1499
2/2
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 12 times.
336 if (hex_string[0]) {
1500 char emit_buf[256];
1501 // Right-pad hex_string with spaces, up to 48 characters.
1502 324 memset(h, ' ', (sizeof(hex_string) - 1) - (h - hex_string));
1503 size_t const bytes_written =
1504 324 snprintf(emit_buf, sizeof(emit_buf), "# %8.8lx %-48.48s |%s|\n",
1505 324 (unsigned long)(hexdump_from + (i & 0xfffffff0)), hex_string,
1506 324 char_string);
1507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 assert(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1508
1/2
✓ Branch 0 taken 324 times.
✗ Branch 1 not taken.
324 write_res = my_b_write(file, (uchar *)emit_buf, bytes_written);
1509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 assert(write_res == 0);
1510 }
1511 /*
1512 need a # to prefix the rest of printouts for example those of
1513 Rows_log_event::print_helper().
1514 */
1515
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 write_res = my_b_write(file, reinterpret_cast<const uchar *>("# "), 2);
1516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
336 assert(write_res == 0);
1517 }
1518 181709 }
1519
1520 /**
1521 Auxiliary function that sets up a conversion table for m_b_write_quoted.
1522
1523 The table has 256 elements. The i'th element is 5 characters, the
1524 first being the length (1..4) and the remaining containing character
1525 #i quoted and not null-terminated. If character #i does not need
1526 quoting (it is >= 32 and not backslash or single-quote), the table
1527 only contains the character itself. A quoted character needs at
1528 most 4 bytes ("\xXX"), plus the length byte, so each element is 5
1529 bytes.
1530
1531 This function is called exactly once even in a multi-threaded
1532 environment, because it is only called in the initializer of a
1533 static variable.
1534
1535 @return Pointer to the table, a 256*5 character array where
1536 character i quoted .
1537 */
1538 2256 static const uchar *get_quote_table() {
1539 static uchar buf[256][5];
1540
2/2
✓ Branch 0 taken 577536 times.
✓ Branch 1 taken 2256 times.
579792 for (int i = 0; i < 256; i++) {
1541 char str[6];
1542
8/8
✓ Branch 0 taken 2256 times.
✓ Branch 1 taken 2256 times.
✓ Branch 2 taken 2256 times.
✓ Branch 3 taken 2256 times.
✓ Branch 4 taken 2256 times.
✓ Branch 5 taken 2256 times.
✓ Branch 6 taken 2256 times.
✓ Branch 7 taken 561744 times.
577536 switch (i) {
1543 2256 case '\b':
1544 2256 strcpy(str, "\\b");
1545 2256 break;
1546 2256 case '\f':
1547 2256 strcpy(str, "\\f");
1548 2256 break;
1549 2256 case '\n':
1550 2256 strcpy(str, "\\n");
1551 2256 break;
1552 2256 case '\r':
1553 2256 strcpy(str, "\\r");
1554 2256 break;
1555 2256 case '\t':
1556 2256 strcpy(str, "\\t");
1557 2256 break;
1558 2256 case '\\':
1559 2256 strcpy(str, "\\\\");
1560 2256 break;
1561 2256 case '\'':
1562 2256 strcpy(str, "\\'");
1563 2256 break;
1564 561744 default:
1565
2/2
✓ Branch 0 taken 60912 times.
✓ Branch 1 taken 500832 times.
561744 if (i < 32)
1566 60912 sprintf(str, "\\x%02x", i);
1567 else {
1568 500832 str[0] = i;
1569 500832 str[1] = '\0';
1570 }
1571 561744 break;
1572 }
1573 577536 buf[i][0] = strlen(str);
1574 577536 memcpy(buf[i] + 1, str, strlen(str));
1575 }
1576 2256 return (const uchar *)(buf);
1577 }
1578
1579 /**
1580 Prints a quoted string to io cache.
1581 Control characters are displayed as hex sequence, e.g. \x00
1582
1583 @param[in] file IO cache
1584 @param[in] ptr Pointer to string
1585 @param[in] length String length
1586
1587 @retval false Success
1588 @retval true Failure
1589 */
1590 28922 static bool my_b_write_quoted(IO_CACHE *file, const uchar *ptr, uint length) {
1591 [[maybe_unused]] int write_res;
1592 const uchar *s;
1593
3/4
✓ Branch 0 taken 2256 times.
✓ Branch 1 taken 26666 times.
✓ Branch 2 taken 2256 times.
✗ Branch 3 not taken.
28922 static const uchar *quote_table = get_quote_table();
1594 28922 my_b_printf(file, "'");
1595
2/2
✓ Branch 0 taken 635942079 times.
✓ Branch 1 taken 28922 times.
635971001 for (s = ptr; length > 0; s++, length--) {
1596 635942079 const uchar *len_and_str = quote_table + *s * 5;
1597 635942079 write_res = my_b_write(file, len_and_str + 1, len_and_str[0]);
1598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 635942079 times.
635942079 assert(write_res == 0);
1599 }
1600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28922 times.
28922 if (my_b_printf(file, "'") == (size_t)-1) return true;
1601 28922 return false;
1602 }
1603
1604 /**
1605 Prints a bit string to io cache in format b'1010'.
1606
1607 @param[in] file IO cache
1608 @param[in] ptr Pointer to string
1609 @param[in] nbits Number of bits
1610 */
1611 2676 static void my_b_write_bit(IO_CACHE *file, const uchar *ptr, uint nbits) {
1612 2676 uint bitnum, nbits8 = ((nbits + 7) / 8) * 8, skip_bits = nbits8 - nbits;
1613 2676 my_b_printf(file, "b'");
1614
2/2
✓ Branch 0 taken 54562 times.
✓ Branch 1 taken 2676 times.
57238 for (bitnum = skip_bits; bitnum < nbits8; bitnum++) {
1615 54562 int is_set = (ptr[(bitnum) / 8] >> (7 - bitnum % 8)) & 0x01;
1616 [[maybe_unused]]
1617
2/2
✓ Branch 0 taken 22128 times.
✓ Branch 1 taken 32434 times.
54562 int write_res = my_b_write(file, (const uchar *)(is_set ? "1" : "0"), 1);
1618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54562 times.
54562 assert(write_res == 0);
1619 }
1620 2676 my_b_printf(file, "'");
1621 2676 }
1622
1623 /**
1624 Prints a packed string to io cache.
1625 The string consists of length packed to 1 or 2 bytes,
1626 followed by string data itself.
1627
1628 @param[in] file IO cache
1629 @param[in] ptr Pointer to string
1630 @param[in] length String size
1631
1632 @retval - number of bytes scanned.
1633 */
1634 9517 static size_t my_b_write_quoted_with_length(IO_CACHE *file, const uchar *ptr,
1635 uint length) {
1636
2/2
✓ Branch 0 taken 6845 times.
✓ Branch 1 taken 2672 times.
9517 if (length < 256) {
1637 6845 length = *ptr;
1638 6845 my_b_write_quoted(file, ptr + 1, length);
1639 6845 return length + 1;
1640 } else {
1641 2672 length = uint2korr(ptr);
1642 2672 my_b_write_quoted(file, ptr + 2, length);
1643 2672 return length + 2;
1644 }
1645 }
1646
1647 /**
1648 Prints a 32-bit number in both signed and unsigned representation
1649
1650 @param[in] file IO cache
1651 @param[in] si Signed number
1652 @param[in] ui Unsigned number
1653 */
1654 17317 static void my_b_write_sint32_and_uint32(IO_CACHE *file, int32 si, uint32 ui) {
1655 17317 my_b_printf(file, "%d", si);
1656
2/2
✓ Branch 0 taken 6922 times.
✓ Branch 1 taken 10395 times.
17317 if (si < 0) my_b_printf(file, " (%u)", ui);
1657 17317 }
1658
1659 #ifndef MYSQL_SERVER
1660 2406 static const char *json_diff_operation_name(enum_json_diff_operation op,
1661 int last_path_char) {
1662
3/4
✓ Branch 0 taken 1686 times.
✓ Branch 1 taken 440 times.
✓ Branch 2 taken 280 times.
✗ Branch 3 not taken.
2406 switch (op) {
1663 1686 case enum_json_diff_operation::REPLACE:
1664 1686 return "JSON_REPLACE";
1665 440 case enum_json_diff_operation::INSERT:
1666
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 320 times.
440 if (last_path_char == ']')
1667 120 return "JSON_ARRAY_INSERT";
1668 else
1669 320 return "JSON_INSERT";
1670 280 case enum_json_diff_operation::REMOVE:
1671 280 return "JSON_REMOVE";
1672 }
1673 /* NOTREACHED */
1674 /* purecov: begin deadcode */
1675 assert(0);
1676 return nullptr;
1677 /* purecov: end */
1678 }
1679
1680 4911 static bool json_wrapper_to_string(IO_CACHE *out, String *buf,
1681 Json_wrapper *wrapper, bool json_type) {
1682
2/4
✓ Branch 0 taken 4911 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4911 times.
4911 if (wrapper->to_string(buf, false, "json_wrapper_to_string", [] {}))
1683 return true; /* purecov: inspected */ // OOM
1684
2/2
✓ Branch 0 taken 2809 times.
✓ Branch 1 taken 2102 times.
4911 if (json_type)
1685 2809 return my_b_write_quoted(out, (uchar *)buf->ptr(), buf->length());
1686
3/4
✓ Branch 0 taken 696 times.
✓ Branch 1 taken 1238 times.
✓ Branch 2 taken 168 times.
✗ Branch 3 not taken.
2102 switch (wrapper->type()) {
1687 696 case enum_json_type::J_NULL:
1688 case enum_json_type::J_DECIMAL:
1689 case enum_json_type::J_INT:
1690 case enum_json_type::J_UINT:
1691 case enum_json_type::J_DOUBLE:
1692 case enum_json_type::J_BOOLEAN:
1693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 696 times.
696 if (my_b_write(out, (uchar *)buf->ptr(), buf->length())) return true;
1694 696 break;
1695 1238 case enum_json_type::J_STRING:
1696 case enum_json_type::J_DATE:
1697 case enum_json_type::J_TIME:
1698 case enum_json_type::J_DATETIME:
1699 case enum_json_type::J_TIMESTAMP:
1700 case enum_json_type::J_OPAQUE:
1701 case enum_json_type::J_ERROR:
1702 1238 my_b_write_quoted(out, (uchar *)buf->ptr(), buf->length());
1703 1238 break;
1704 168 case enum_json_type::J_OBJECT:
1705 case enum_json_type::J_ARRAY:
1706 168 my_b_printf(out, "CAST(");
1707 168 my_b_write_quoted(out, (uchar *)buf->ptr(), buf->length());
1708 168 my_b_printf(out, " AS JSON)");
1709 168 break;
1710 default:
1711 assert(0); /* purecov: deadcode */
1712 }
1713 2102 return false;
1714 }
1715
1716 2258 static const char *print_json_diff(IO_CACHE *out, const uchar *data,
1717 size_t length, const char *col_name) {
1718
1/2
✓ Branch 0 taken 2258 times.
✗ Branch 1 not taken.
2258 DBUG_TRACE;
1719
1720 static const char *line_separator = "\n### ";
1721
1722 // read length
1723 2258 const uchar *p = data;
1724
1725 2258 const uchar *start_p = p;
1726 2258 size_t start_length = length;
1727
1728 // Read the list of operations.
1729 2258 std::vector<const char *> operation_names;
1730
2/2
✓ Branch 0 taken 2430 times.
✓ Branch 1 taken 2216 times.
4646 while (length) {
1731 // read operation
1732 2430 int operation_int = *p;
1733
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2424 times.
2430 if (operation_int >= JSON_DIFF_OPERATION_COUNT)
1734 42 return "reading operation type (invalid operation code)";
1735 2424 enum_json_diff_operation operation =
1736 static_cast<enum_json_diff_operation>(operation_int);
1737 2424 p++;
1738 2424 length--;
1739
1740 // skip path
1741 size_t path_length;
1742
3/4
✓ Branch 0 taken 2424 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 2412 times.
2424 if (net_field_length_checked<size_t>(&p, &length, &path_length))
1743 12 return "reading path length to skip";
1744
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2406 times.
2412 if (path_length > length) return "skipping path";
1745 2406 p += path_length;
1746 2406 length -= path_length;
1747
1748 // compute operation name
1749 2406 const char *operation_name = json_diff_operation_name(operation, p[-1]);
1750
1/2
✓ Branch 0 taken 2406 times.
✗ Branch 1 not taken.
2406 operation_names.push_back(operation_name);
1751
1752 // skip value
1753
2/2
✓ Branch 0 taken 2126 times.
✓ Branch 1 taken 280 times.
2406 if (operation != enum_json_diff_operation::REMOVE) {
1754 size_t value_length;
1755
3/4
✓ Branch 0 taken 2126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 2114 times.
2126 if (net_field_length_checked<size_t>(&p, &length, &value_length))
1756 18 return "reading value length to skip";
1757
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2108 times.
2114 if (value_length > length) return "skipping value";
1758 2108 p += value_length;
1759 2108 length -= value_length;
1760 }
1761 }
1762
1763 // Print function names in reverse order.
1764 2216 bool printed = false;
1765
2/2
✓ Branch 0 taken 2388 times.
✓ Branch 1 taken 2216 times.
4604 for (int i = operation_names.size() - 1; i >= 0; i--) {
1766
6/6
✓ Branch 0 taken 920 times.
✓ Branch 1 taken 1468 times.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 760 times.
✓ Branch 4 taken 1628 times.
✓ Branch 5 taken 760 times.
2388 if (i == 0 || operation_names[i - 1] != operation_names[i]) {
1767
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 1468 times.
1628 if (printed)
1768
2/4
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 160 times.
160 if (my_b_printf(out, "%s", line_separator) == (size_t)-1)
1769 return "printing line separator";
1770 /* purecov: inspected */ // error writing to output
1771
2/4
✓ Branch 0 taken 1628 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1628 times.
1628 if (my_b_printf(out, "%s(", operation_names[i]) == (size_t)-1)
1772 return "printing function name";
1773 /* purecov: inspected */ // error writing to output
1774 1628 printed = true;
1775 }
1776 }
1777
1778 // Print column id
1779
2/4
✓ Branch 0 taken 2216 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2216 times.
2216 if (my_b_printf(out, "%s", col_name) == (size_t)-1)
1780 return "printing column id";
1781 /* purecov: inspected */ // error writing to output
1782
1783 // In case this vector is empty (a no-op), make an early return
1784 // after printing only the column name
1785
2/2
✓ Branch 0 taken 748 times.
✓ Branch 1 taken 1468 times.
2216 if (operation_names.size() == 0) return nullptr;
1786
1787 // Print comma between column name and next function argument
1788
2/4
✓ Branch 0 taken 1468 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1468 times.
1468 if (my_b_printf(out, ", ") == (size_t)-1) return "printing comma";
1789 /* purecov: inspected */ // error writing to output
1790
1791 // Print paths and values.
1792 1468 p = start_p;
1793 1468 length = start_length;
1794 1468 StringBuffer<STRING_BUFFER_USUAL_SIZE> buf;
1795 1468 int diff_i = 0;
1796
2/2
✓ Branch 0 taken 2388 times.
✓ Branch 1 taken 1462 times.
3850 while (length) {
1797 // Read operation
1798 2388 enum_json_diff_operation operation = (enum_json_diff_operation)*p;
1799 2388 p++;
1800 2388 length--;
1801
1802 // Read path length
1803 size_t path_length;
1804
2/4
✓ Branch 0 taken 2388 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2388 times.
2388 if (net_field_length_checked<size_t>(&p, &length, &path_length))
1805 6 return "reading path length";
1806 /* purecov: deadcode */ // already checked in loop above
1807
1808 // Print path
1809
2/4
✓ Branch 0 taken 2388 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2388 times.
2388 if (my_b_write_quoted(out, p, path_length)) return "printing path";
1810 /* purecov: inspected */ // error writing to output
1811 2388 p += path_length;
1812 2388 length -= path_length;
1813
1814
2/2
✓ Branch 0 taken 2108 times.
✓ Branch 1 taken 280 times.
2388 if (operation != enum_json_diff_operation::REMOVE) {
1815 // Print comma between path and value
1816
2/4
✓ Branch 0 taken 2108 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2108 times.
2114 if (my_b_printf(out, ", ") == (size_t)-1) return "printing comma";
1817 /* purecov: inspected */ // error writing to output
1818
1819 // Read value length
1820 size_t value_length;
1821
2/4
✓ Branch 0 taken 2108 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2108 times.
2108 if (net_field_length_checked<size_t>(&p, &length, &value_length))
1822 return "reading value length";
1823 /* purecov: deadcode */ // already checked in loop above
1824
1825 // Read value
1826 json_binary::Value value =
1827
1/2
✓ Branch 0 taken 2108 times.
✗ Branch 1 not taken.
2108 json_binary::parse_binary((const char *)p, value_length);
1828 2108 p += value_length;
1829 2108 length -= value_length;
1830
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2102 times.
2108 if (value.type() == json_binary::Value::ERROR)
1831 6 return "parsing json value";
1832
1/2
✓ Branch 0 taken 2102 times.
✗ Branch 1 not taken.
2102 Json_wrapper wrapper(value);
1833
1834 // Print value
1835 2102 buf.length(0);
1836
2/4
✓ Branch 0 taken 2102 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2102 times.
2102 if (json_wrapper_to_string(out, &buf, &wrapper, false))
1837 return "converting json to string";
1838 /* purecov: inspected */ // OOM
1839 2102 buf.length(0);
1840
1/2
✓ Branch 0 taken 2102 times.
✗ Branch 1 not taken.
2102 }
1841
1842 // Print closing parenthesis
1843
6/6
✓ Branch 0 taken 920 times.
✓ Branch 1 taken 1462 times.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 760 times.
✓ Branch 4 taken 1622 times.
✓ Branch 5 taken 760 times.
2382 if (length == 0 || operation_names[diff_i + 1] != operation_names[diff_i])
1844
2/4
✓ Branch 0 taken 1622 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1622 times.
1622 if (my_b_printf(out, ")") == (size_t)-1)
1845 return "printing closing parenthesis";
1846 /* purecov: inspected */ // error writing to output
1847
1848 // Print ending comma
1849
2/2
✓ Branch 0 taken 920 times.
✓ Branch 1 taken 1462 times.
2382 if (length != 0)
1850
2/4
✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 920 times.
920 if (my_b_printf(out, ",%s", line_separator) == (size_t)-1)
1851 return "printing comma";
1852 /* purecov: inspected */ // error writing to output
1853
1854 2382 diff_i++;
1855 }
1856
1857 1462 return nullptr;
1858 2258 }
1859 #endif // ifndef MYSQL_SERVER
1860
1861 /**
1862 Print a packed value of the given SQL type into IO cache
1863
1864 @param[in] file IO cache
1865 @param[in] ptr Pointer to string
1866 @param[in] type Column type
1867 @param[in] meta Column meta information
1868 @param[out] typestr SQL type string buffer (for verbose output)
1869 @param[in] typestr_length Size of typestr
1870 @param[in] col_name Column name
1871 @param[in] is_partial True if this is a JSON column that will be
1872 read in partial format, false otherwise.
1873
1874 @retval 0 on error
1875 @retval number of bytes scanned from ptr for non-NULL fields, or
1876 another positive number for NULL fields
1877 */
1878 #ifndef MYSQL_SERVER
1879 66710 static size_t log_event_print_value(IO_CACHE *file, const uchar *ptr, uint type,
1880 uint meta, char *typestr,
1881 size_t typestr_length, char *col_name,
1882 bool is_partial) {
1883 66710 uint32 length = 0;
1884
1885
2/2
✓ Branch 0 taken 4854 times.
✓ Branch 1 taken 61856 times.
66710 if (type == MYSQL_TYPE_STRING) {
1886
1/2
✓ Branch 0 taken 4854 times.
✗ Branch 1 not taken.
4854 if (meta >= 256) {
1887 4854 uint byte0 = meta >> 8;
1888 4854 uint byte1 = meta & 0xFF;
1889
1890
2/2
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 4706 times.
4854 if ((byte0 & 0x30) != 0x30) {
1891 /* a long CHAR() field: see #37426 */
1892 148 length = byte1 | (((byte0 & 0x30) ^ 0x30) << 4);
1893 148 type = byte0 | 0x30;
1894 } else
1895 4706 length = meta & 0xFF;
1896 } else
1897 length = meta;
1898 }
1899
1900
20/24
✓ Branch 0 taken 10201 times.
✓ Branch 1 taken 4744 times.
✓ Branch 2 taken 3182 times.
✓ Branch 3 taken 206 times.
✓ Branch 4 taken 3238 times.
✓ Branch 5 taken 3174 times.
✓ Branch 6 taken 3227 times.
✓ Branch 7 taken 3172 times.
✓ Branch 8 taken 1900 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1592 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1592 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1592 times.
✓ Branch 15 taken 1256 times.
✓ Branch 16 taken 812 times.
✓ Branch 17 taken 812 times.
✓ Branch 18 taken 824 times.
✓ Branch 19 taken 9856 times.
✓ Branch 20 taken 5179 times.
✓ Branch 21 taken 4854 times.
✓ Branch 22 taken 5297 times.
✗ Branch 23 not taken.
66710 switch (type) {
1901 10201 case MYSQL_TYPE_LONG: {
1902 10201 snprintf(typestr, typestr_length, "INT");
1903
2/2
✓ Branch 0 taken 856 times.
✓ Branch 1 taken 9345 times.
10201 if (!ptr) return my_b_printf(file, "NULL");
1904 9345 int32 si = sint4korr(ptr);
1905 9345 uint32 ui = uint4korr(ptr);
1906 9345 my_b_write_sint32_and_uint32(file, si, ui);
1907 9345 return 4;
1908 }
1909
1910 4744 case MYSQL_TYPE_TINY: {
1911 4744 snprintf(typestr, typestr_length, "TINYINT");
1912
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 4680 times.
4744 if (!ptr) return my_b_printf(file, "NULL");
1913 4680 my_b_write_sint32_and_uint32(file, (int)(signed char)*ptr,
1914 4680 (uint)(unsigned char)*ptr);
1915 4680 return 1;
1916 }
1917
1918 3182 case MYSQL_TYPE_SHORT: {
1919 3182 snprintf(typestr, typestr_length, "SHORTINT");
1920
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3134 times.
3182 if (!ptr) return my_b_printf(file, "NULL");
1921 3134 int32 si = (int32)sint2korr(ptr);
1922 3134 uint32 ui = (uint32)uint2korr(ptr);
1923 3134 my_b_write_sint32_and_uint32(file, si, ui);
1924 3134 return 2;
1925 }
1926
1927 206 case MYSQL_TYPE_INT24: {
1928 206 snprintf(typestr, typestr_length, "MEDIUMINT");
1929
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 158 times.
206 if (!ptr) return my_b_printf(file, "NULL");
1930 158 int32 si = sint3korr(ptr);
1931 158 uint32 ui = uint3korr(ptr);
1932 158 my_b_write_sint32_and_uint32(file, si, ui);
1933 158 return 3;
1934 }
1935
1936 3238 case MYSQL_TYPE_LONGLONG: {
1937 3238 snprintf(typestr, typestr_length, "LONGINT");
1938
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3190 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
3238 if (!ptr) return my_b_printf(file, "NULL");
1939 char tmp[64];
1940 3190 longlong si = sint8korr(ptr);
1941
1/2
✓ Branch 0 taken 3190 times.
✗ Branch 1 not taken.
3190 longlong10_to_str(si, tmp, -10);
1942
1/2
✓ Branch 0 taken 3190 times.
✗ Branch 1 not taken.
3190 my_b_printf(file, "%s", tmp);
1943
2/2
✓ Branch 0 taken 1544 times.
✓ Branch 1 taken 1646 times.
3190 if (si < 0) {
1944 1544 ulonglong ui = uint8korr(ptr);
1945
1/2
✓ Branch 0 taken 1544 times.
✗ Branch 1 not taken.
1544 longlong10_to_str((longlong)ui, tmp, 10);
1946
1/2
✓ Branch 0 taken 1544 times.
✗ Branch 1 not taken.
1544 my_b_printf(file, " (%s)", tmp);
1947 }
1948 3190 return 8;
1949 }
1950
1951 3174 case MYSQL_TYPE_NEWDECIMAL: {
1952 3174 uint precision = meta >> 8;
1953 3174 uint decimals = meta & 0xFF;
1954 3174 snprintf(typestr, typestr_length, "DECIMAL(%d,%d)", precision, decimals);
1955
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3126 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
3174 if (!ptr) return my_b_printf(file, "NULL");
1956
1/2
✓ Branch 0 taken 3126 times.
✗ Branch 1 not taken.
3126 uint bin_size = my_decimal_get_binary_size(precision, decimals);
1957 3126 my_decimal dec;
1958
1/2
✓ Branch 0 taken 3126 times.
✗ Branch 1 not taken.
3126 binary2my_decimal(E_DEC_FATAL_ERROR, pointer_cast<const uchar *>(ptr),
1959 &dec, precision, decimals);
1960 char buff[DECIMAL_MAX_STR_LENGTH + 1];
1961 3126 int len = sizeof(buff);
1962
1/2
✓ Branch 0 taken 3126 times.
✗ Branch 1 not taken.
3126 decimal2string(&dec, buff, &len);
1963
1/2
✓ Branch 0 taken 3126 times.
✗ Branch 1 not taken.
3126 my_b_printf(file, "%s", buff);
1964 3126 return bin_size;
1965 3126 }
1966
1967 3227 case MYSQL_TYPE_FLOAT: {
1968 3227 snprintf(typestr, typestr_length, "FLOAT");
1969
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3179 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
3227 if (!ptr) return my_b_printf(file, "NULL");
1970 3179 float fl = float4get(ptr);
1971 char tmp[320];
1972 3179 sprintf(tmp, "%-20g", (double)fl);
1973
1/2
✓ Branch 0 taken 3179 times.
✗ Branch 1 not taken.
3179 my_b_printf(file, "%s", tmp); /* my_b_printf doesn't support %-20g */
1974 3179 return 4;
1975 }
1976
1977 3172 case MYSQL_TYPE_DOUBLE: {
1978 3172 strcpy(typestr, "DOUBLE");
1979
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3124 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
3172 if (!ptr) return my_b_printf(file, "NULL");
1980 3124 double dbl = float8get(ptr);
1981 char tmp[320];
1982 3124 sprintf(tmp, "%-.20g", dbl); /* my_b_printf doesn't support %-20g */
1983
1/2
✓ Branch 0 taken 3124 times.
✗ Branch 1 not taken.
3124 my_b_printf(file, "%s", tmp);
1984 3124 return 8;
1985 }
1986
1987 1900 case MYSQL_TYPE_BIT: {
1988 /* Meta-data: bit_len, bytes_in_rec, 2 bytes */
1989 1900 uint nbits = ((meta >> 8) * 8) + (meta & 0xFF);
1990 1900 snprintf(typestr, typestr_length, "BIT(%d)", nbits);
1991
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1868 times.
1900 if (!ptr) return my_b_printf(file, "NULL");
1992 1868 length = (nbits + 7) / 8;
1993 1868 my_b_write_bit(file, ptr, nbits);
1994 1868 return length;
1995 }
1996
1997 case MYSQL_TYPE_TIMESTAMP: {
1998 snprintf(typestr, typestr_length, "TIMESTAMP");
1999 if (!ptr) return my_b_printf(file, "NULL");
2000 uint32 i32 = uint4korr(ptr);
2001 my_b_printf(file, "%d", i32);
2002 return 4;
2003 }
2004
2005 1592 case MYSQL_TYPE_TIMESTAMP2: {
2006 1592 snprintf(typestr, typestr_length, "TIMESTAMP(%d)", meta);
2007
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1576 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
1592 if (!ptr) return my_b_printf(file, "NULL");
2008 char buf[MAX_DATE_STRING_REP_LENGTH];
2009 my_timeval tm;
2010
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 my_timestamp_from_binary(&tm, ptr, meta);
2011
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 int buflen = my_timeval_to_str(&tm, buf, meta);
2012
2/4
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1576 times.
1576 if (my_b_write(file, pointer_cast<uchar *>(buf), buflen)) return 0;
2013
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 return my_timestamp_binary_length(meta);
2014 }
2015
2016 case MYSQL_TYPE_DATETIME: {
2017 snprintf(typestr, typestr_length, "DATETIME");
2018 if (!ptr) return my_b_printf(file, "NULL");
2019 size_t d, t;
2020 uint64 i64 = uint8korr(ptr); /* YYYYMMDDhhmmss */
2021 d = static_cast<size_t>(i64 / 1000000);
2022 t = i64 % 1000000;
2023 my_b_printf(file, "%04d-%02d-%02d %02d:%02d:%02d",
2024 static_cast<int>(d / 10000),
2025 static_cast<int>(d % 10000) / 100, static_cast<int>(d % 100),
2026 static_cast<int>(t / 10000),
2027 static_cast<int>(t % 10000) / 100, static_cast<int>(t % 100));
2028 return 8;
2029 }
2030
2031 1592 case MYSQL_TYPE_DATETIME2: {
2032 1592 snprintf(typestr, typestr_length, "DATETIME(%d)", meta);
2033
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1576 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
1592 if (!ptr) return my_b_printf(file, "NULL");
2034 char buf[MAX_DATE_STRING_REP_LENGTH];
2035 MYSQL_TIME ltime;
2036
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 longlong packed = my_datetime_packed_from_binary(ptr, meta);
2037
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 TIME_from_longlong_datetime_packed(&ltime, packed);
2038
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 int buflen = my_datetime_to_str(ltime, buf, meta);
2039
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 my_b_write_quoted(file, (uchar *)buf, buflen);
2040
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 return my_datetime_binary_length(meta);
2041 }
2042
2043 case MYSQL_TYPE_TIME: {
2044 snprintf(typestr, typestr_length, "TIME");
2045 if (!ptr) return my_b_printf(file, "NULL");
2046 uint32 i32 = uint3korr(ptr);
2047 my_b_printf(file, "'%02d:%02d:%02d'", i32 / 10000, (i32 % 10000) / 100,
2048 i32 % 100);
2049 return 3;
2050 }
2051
2052 1592 case MYSQL_TYPE_TIME2: {
2053 1592 snprintf(typestr, typestr_length, "TIME(%d)", meta);
2054
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1576 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
1592 if (!ptr) return my_b_printf(file, "NULL");
2055 char buf[MAX_DATE_STRING_REP_LENGTH];
2056 MYSQL_TIME ltime;
2057
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 longlong packed = my_time_packed_from_binary(ptr, meta);
2058
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 TIME_from_longlong_time_packed(&ltime, packed);
2059
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 int buflen = my_time_to_str(ltime, buf, meta);
2060
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 my_b_write_quoted(file, (uchar *)buf, buflen);
2061
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 return my_time_binary_length(meta);
2062 }
2063
2064 1256 case MYSQL_TYPE_NEWDATE: {
2065 1256 snprintf(typestr, typestr_length, "DATE");
2066
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1240 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
1256 if (!ptr) return my_b_printf(file, "NULL");
2067 1240 uint32 tmp = uint3korr(ptr);
2068 int part;
2069 char buf[11];
2070 1240 char *pos = &buf[10]; // start from '\0' to the beginning
2071
2072 /* Copied from field.cc */
2073 1240 *pos-- = 0; // End NULL
2074 1240 part = (int)(tmp & 31);
2075 1240 *pos-- = (char)('0' + part % 10);
2076 1240 *pos-- = (char)('0' + part / 10);
2077 1240 *pos-- = ':';
2078 1240 part = (int)(tmp >> 5 & 15);
2079 1240 *pos-- = (char)('0' + part % 10);
2080 1240 *pos-- = (char)('0' + part / 10);
2081 1240 *pos-- = ':';
2082 1240 part = (int)(tmp >> 9);
2083 1240 *pos-- = (char)('0' + part % 10);
2084 1240 part /= 10;
2085 1240 *pos-- = (char)('0' + part % 10);
2086 1240 part /= 10;
2087 1240 *pos-- = (char)('0' + part % 10);
2088 1240 part /= 10;
2089 1240 *pos = (char)('0' + part);
2090
1/2
✓ Branch 0 taken 1240 times.
✗ Branch 1 not taken.
1240 my_b_printf(file, "'%s'", buf);
2091 1240 return 3;
2092 }
2093
2094 812 case MYSQL_TYPE_YEAR: {
2095 812 snprintf(typestr, typestr_length, "YEAR");
2096
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 796 times.
812 if (!ptr) return my_b_printf(file, "NULL");
2097 796 uint32 i32 = *ptr;
2098 796 my_b_printf(file, "%04d", i32 + 1900);
2099 796 return 1;
2100 }
2101
2102 812 case MYSQL_TYPE_ENUM:
2103
1/3
✓ Branch 0 taken 812 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
812 switch (meta & 0xFF) {
2104 812 case 1:
2105 812 snprintf(typestr, typestr_length, "ENUM(1 byte)");
2106
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 796 times.
812 if (!ptr) return my_b_printf(file, "NULL");
2107 796 my_b_printf(file, "%d", (int)*ptr);
2108 796 return 1;
2109 case 2: {
2110 snprintf(typestr, typestr_length, "ENUM(2 bytes)");
2111 if (!ptr) return my_b_printf(file, "NULL");
2112 int32 i32 = uint2korr(ptr);
2113 my_b_printf(file, "%d", i32);
2114 return 2;
2115 }
2116 default:
2117 my_b_printf(file, "!! Unknown ENUM packlen=%d", meta & 0xFF);
2118 return 0;
2119 }
2120 break;
2121
2122 824 case MYSQL_TYPE_SET:
2123 824 snprintf(typestr, typestr_length, "SET(%d bytes)", meta & 0xFF);
2124
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 808 times.
824 if (!ptr) return my_b_printf(file, "NULL");
2125 808 my_b_write_bit(file, ptr, (meta & 0xFF) * 8);
2126 808 return meta & 0xFF;
2127
2128 9856 case MYSQL_TYPE_BLOB:
2129
4/5
✓ Branch 0 taken 3684 times.
✓ Branch 1 taken 2255 times.
✓ Branch 2 taken 1948 times.
✓ Branch 3 taken 1969 times.
✗ Branch 4 not taken.
9856 switch (meta) {
2130 3684 case 1:
2131 3684 snprintf(typestr, typestr_length, "TINYBLOB/TINYTEXT");
2132
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3636 times.
3684 if (!ptr) return my_b_printf(file, "NULL");
2133 3636 length = *ptr;
2134 3636 my_b_write_quoted(file, ptr + 1, length);
2135 3636 return length + 1;
2136 2255 case 2:
2137 2255 snprintf(typestr, typestr_length, "BLOB/TEXT");
2138
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 2193 times.
2255 if (!ptr) return my_b_printf(file, "NULL");
2139 2193 length = uint2korr(ptr);
2140 2193 my_b_write_quoted(file, ptr + 2, length);
2141 2193 return length + 2;
2142 1948 case 3:
2143 1948 snprintf(typestr, typestr_length, "MEDIUMBLOB/MEDIUMTEXT");
2144
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1900 times.
1948 if (!ptr) return my_b_printf(file, "NULL");
2145 1900 length = uint3korr(ptr);
2146 1900 my_b_write_quoted(file, ptr + 3, length);
2147 1900 return length + 3;
2148 1969 case 4:
2149 1969 snprintf(typestr, typestr_length, "LONGBLOB/LONGTEXT");
2150
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1921 times.
1969 if (!ptr) return my_b_printf(file, "NULL");
2151 1921 length = uint4korr(ptr);
2152 1921 my_b_write_quoted(file, ptr + 4, length);
2153 1921 return length + 4;
2154 default:
2155 my_b_printf(file, "!! Unknown BLOB packlen=%d", length);
2156 return 0;
2157 }
2158
2159 5179 case MYSQL_TYPE_VARCHAR:
2160 case MYSQL_TYPE_VAR_STRING:
2161 5179 length = meta;
2162 5179 snprintf(typestr, typestr_length, "VARSTRING(%d)", length);
2163
2/2
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 4919 times.
5179 if (!ptr) return my_b_printf(file, "NULL");
2164 4919 return my_b_write_quoted_with_length(file, ptr, length);
2165
2166 4854 case MYSQL_TYPE_STRING:
2167 4854 snprintf(typestr, typestr_length, "STRING(%d)", length);
2168
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 4598 times.
4854 if (!ptr) return my_b_printf(file, "NULL");
2169 4598 return my_b_write_quoted_with_length(file, ptr, length);
2170
2171 5297 case MYSQL_TYPE_JSON: {
2172 5297 snprintf(typestr, typestr_length, "JSON");
2173
2/2
✓ Branch 0 taken 230 times.
✓ Branch 1 taken 5067 times.
5297 if (!ptr) return my_b_printf(file, "NULL");
2174 5067 length = uint4korr(ptr);
2175 5067 ptr += 4;
2176
2/2
✓ Branch 0 taken 2258 times.
✓ Branch 1 taken 2809 times.
5067 if (is_partial) {
2177 2258 const char *error = print_json_diff(file, ptr, length, col_name);
2178
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 2210 times.
2258 if (error != nullptr)
2179 48 my_b_printf(file, "Error %s while printing JSON diff\n", error);
2180 } else {
2181 json_binary::Value value =
2182
1/2
✓ Branch 0 taken 2809 times.
✗ Branch 1 not taken.
2809 json_binary::parse_binary((const char *)ptr, length);
2183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2809 times.
2809 if (value.type() == json_binary::Value::ERROR) {
2184 if (my_b_printf(
2185 file,
2186 "Invalid JSON\n")) /* purecov: inspected */ // corrupted
2187 // event
2188 return 0; /* purecov: inspected */ // error writing output
2189 } else {
2190
1/2
✓ Branch 0 taken 2809 times.
✗ Branch 1 not taken.
2809 Json_wrapper wrapper(value);
2191 2809 StringBuffer<STRING_BUFFER_USUAL_SIZE> s;
2192
2/4
✓ Branch 0 taken 2809 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2809 times.
2809 if (json_wrapper_to_string(file, &s, &wrapper, true))
2193 my_b_printf(file, "Failed to format JSON object as string.\n");
2194 /* purecov: inspected */ // OOM
2195 2809 }
2196 }
2197 5067 return length + meta;
2198 }
2199 case MYSQL_TYPE_BOOL:
2200 case MYSQL_TYPE_INVALID:
2201 default: {
2202 char tmp[5];
2203 snprintf(tmp, sizeof(tmp), "%04x", meta);
2204 my_b_printf(file,
2205 "!! Don't know how to handle column type=%d meta=%d (%s)\n",
2206 type, meta, tmp);
2207 } break;
2208 }
2209 *typestr = 0;
2210 return 0;
2211 }
2212 #endif
2213
2214 /**
2215 Print a packed row into IO cache
2216
2217 @param[in] file IO cache
2218 @param[in] td Table definition
2219 @param[in] print_event_info Print parameters
2220 @param[in] cols_bitmap Column bitmaps.
2221 @param[in] value Pointer to packed row
2222 @param[in] prefix Row's SQL clause ("SET", "WHERE", etc)
2223
2224 @retval - number of bytes scanned.
2225 */
2226
2227 7179 size_t Rows_log_event::print_verbose_one_row(
2228 IO_CACHE *file, table_def *td, PRINT_EVENT_INFO *print_event_info,
2229 MY_BITMAP *cols_bitmap, const uchar *value, const uchar *prefix,
2230 enum_row_image_type row_image_type) {
2231 7179 const uchar *value0 = value;
2232 7179 char typestr[64] = "";
2233
2234 // Read value_options if this is AI for PARTIAL_UPDATE_ROWS_EVENT
2235 7179 ulonglong value_options = 0;
2236
1/2
✓ Branch 0 taken 7179 times.
✗ Branch 1 not taken.
7179 Bit_reader partial_bits;
2237
6/6
✓ Branch 0 taken 5230 times.
✓ Branch 1 taken 1949 times.
✓ Branch 2 taken 2615 times.
✓ Branch 3 taken 2615 times.
✓ Branch 4 taken 2615 times.
✓ Branch 5 taken 4564 times.
7179 if (get_type_code() == binary_log::PARTIAL_UPDATE_ROWS_EVENT &&
2238 row_image_type == enum_row_image_type::UPDATE_AI) {
2239 2615 size_t length = m_rows_end - value;
2240
2/4
✓ Branch 0 taken 2615 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2615 times.
2615 if (net_field_length_checked<ulonglong>(&value, &length, &value_options)) {
2241 my_b_printf(file,
2242 "*** Error reading binlog_row_value_options from "
2243 "Partial_update_rows_log_event\n");
2244 return 0;
2245 }
2246
2/2
✓ Branch 0 taken 1850 times.
✓ Branch 1 taken 765 times.
2615 if ((value_options & PARTIAL_JSON_UPDATES) != 0) {
2247 1850 partial_bits.set_ptr(value);
2248
1/2
✓ Branch 0 taken 1850 times.
✗ Branch 1 not taken.
1850 value += (td->json_column_count() + 7) / 8;
2249 }
2250 }
2251
2252 /*
2253 Metadata bytes which gives the information about nullabity of
2254 master columns. Master writes one bit for each column in the
2255 image.
2256 */
2257
1/2
✓ Branch 0 taken 7179 times.
✗ Branch 1 not taken.
7179 Bit_reader null_bits(value);
2258
1/2
✓ Branch 0 taken 7179 times.
✗ Branch 1 not taken.
7179 value += (bitmap_bits_set(cols_bitmap) + 7) / 8;
2259
2260
1/2
✓ Branch 0 taken 7179 times.
✗ Branch 1 not taken.
7179 my_b_printf(file, "%s", prefix);
2261
2262
2/2
✓ Branch 0 taken 83288 times.
✓ Branch 1 taken 7179 times.
90467 for (size_t i = 0; i < td->size(); i++) {
2263 /*
2264 Note: need to read partial bit before reading cols_bitmap, since
2265 the partial_bits bitmap has a bit for every JSON column
2266 regardless of whether it is included in the bitmap or not.
2267 */
2268
1/2
✓ Branch 0 taken 34968 times.
✗ Branch 1 not taken.
34968 bool is_partial = (value_options & PARTIAL_JSON_UPDATES) != 0 &&
2269
2/2
✓ Branch 0 taken 2478 times.
✓ Branch 1 taken 32490 times.
34968 row_image_type == enum_row_image_type::UPDATE_AI &&
2270
4/4
✓ Branch 0 taken 34968 times.
✓ Branch 1 taken 48320 times.
✓ Branch 2 taken 2258 times.
✓ Branch 3 taken 220 times.
153224 td->type(i) == MYSQL_TYPE_JSON && partial_bits.get();
2271
2272
2/2
✓ Branch 0 taken 16578 times.
✓ Branch 1 taken 66710 times.
83288 if (bitmap_is_set(cols_bitmap, i) == 0) continue;
2273
2274 66710 bool is_null = null_bits.get();
2275
2276
1/2
✓ Branch 0 taken 66710 times.
✗ Branch 1 not taken.
66710 my_b_printf(file, "### @%d=", static_cast<int>(i + 1));
2277
2/2
✓ Branch 0 taken 64406 times.
✓ Branch 1 taken 2304 times.
66710 if (!is_null) {
2278 size_t fsize =
2279
1/2
✓ Branch 0 taken 64406 times.
✗ Branch 1 not taken.
64406 td->calc_field_size((uint)i, pointer_cast<const uchar *>(value));
2280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64406 times.
64406 if (fsize > (size_t)(m_rows_end - value)) {
2281 my_b_printf(file,
2282 "***Corrupted replication event was detected: "
2283 "field size is set to %u, but there are only %u bytes "
2284 "left of the event. Not printing the value***\n",
2285 (uint)fsize, (uint)(m_rows_end - value));
2286 return 0;
2287 }
2288 }
2289 char col_name[256];
2290 66710 sprintf(col_name, "@%lu", (unsigned long)i + 1);
2291
3/4
✓ Branch 0 taken 2304 times.
✓ Branch 1 taken 64406 times.
✓ Branch 2 taken 66710 times.
✗ Branch 3 not taken.
133420 size_t size = log_event_print_value(
2292 66710 file, is_null ? nullptr : value, td->type(i), td->field_metadata(i),
2293 typestr, sizeof(typestr), col_name, is_partial);
2294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66710 times.
66710 if (!size) return 0;
2295
2296
2/2
✓ Branch 0 taken 64406 times.
✓ Branch 1 taken 2304 times.
66710 if (!is_null) value += size;
2297
2298
2/2
✓ Branch 0 taken 7624 times.
✓ Branch 1 taken 59086 times.
66710 if (print_event_info->verbose > 1) {
2299
1/2
✓ Branch 0 taken 7624 times.
✗ Branch 1 not taken.
7624 my_b_printf(file, " /* ");
2300
2301
1/2
✓ Branch 0 taken 7624 times.
✗ Branch 1 not taken.
7624 my_b_printf(file, "%s ", typestr);
2302
2303
1/2
✓ Branch 0 taken 7624 times.
✗ Branch 1 not taken.
7624 my_b_printf(file, "meta=%d nullable=%d is_null=%d ",
2304 7624 td->field_metadata(i), td->maybe_null(i), is_null);
2305
1/2
✓ Branch 0 taken 7624 times.
✗ Branch 1 not taken.
7624 my_b_printf(file, "*/");
2306 }
2307
2308
1/2
✓ Branch 0 taken 66710 times.
✗ Branch 1 not taken.
66710 my_b_printf(file, "\n");
2309 }
2310 7179 return value - value0;
2311 }
2312
2313 /**
2314 Print a row event into IO cache in human readable form (in SQL format)
2315
2316 @param[in] file IO cache
2317 @param[in] print_event_info Print parameters
2318 */
2319 3355 void Rows_log_event::print_verbose(IO_CACHE *file,
2320 PRINT_EVENT_INFO *print_event_info) {
2321 // Quoted length of the identifier can be twice the original length
2322 char quoted_db[1 + NAME_LEN * 2 + 2];
2323 char quoted_table[1 + NAME_LEN * 2 + 2];
2324 size_t quoted_db_len, quoted_table_len;
2325 Table_map_log_event *map;
2326 table_def *td;
2327 const char *sql_command, *sql_clause1, *sql_clause2;
2328
1/2
✓ Branch 0 taken 3355 times.
✗ Branch 1 not taken.
3355 Log_event_type general_type_code = get_general_type_code();
2329
2330 enum_row_image_type row_image_type =
2331
1/2
✓ Branch 0 taken 3355 times.
✗ Branch 1 not taken.
3355 get_general_type_code() == binary_log::WRITE_ROWS_EVENT
2332
2/2
✓ Branch 0 taken 2818 times.
✓ Branch 1 taken 537 times.
6173 ? enum_row_image_type::WRITE_AI
2333
1/2
✓ Branch 0 taken 2818 times.
✗ Branch 1 not taken.
2818 : get_general_type_code() == binary_log::DELETE_ROWS_EVENT
2334
2/2
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 2563 times.
2818 ? enum_row_image_type::DELETE_BI
2335 3355 : enum_row_image_type::UPDATE_BI;
2336
2337
4/4
✓ Branch 0 taken 3339 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 3338 times.
6694 if (m_extra_row_info.have_ndb_info() ||
2338
3/4
✓ Branch 0 taken 3339 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3338 times.
3339 DBUG_EVALUATE_IF("simulate_error_in_ndb_info_print", 1, 0)) {
2339 int extra_row_ndb_info_payload_len =
2340
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 m_extra_row_info.get_ndb_length() - EXTRA_ROW_INFO_HEADER_LENGTH;
2341
2342
3/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 16 times.
17 if (m_extra_row_info.get_ndb_length() < EXTRA_ROW_INFO_HEADER_LENGTH) {
2343
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_b_printf(file,
2344 "***Error: The number of extra_row_ndb_info is smaller"
2345 " than the minimum acceptable value.\n");
2346 1 return;
2347 }
2348 16 unsigned char *ndb_info = m_extra_row_info.get_ndb_info();
2349 16 my_b_printf(file, "### Extra row ndb info: data_format: %u, len: %u, ",
2350
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 ndb_info[EXTRA_ROW_INFO_FORMAT_OFFSET],
2351 extra_row_ndb_info_payload_len);
2352 /*
2353 Buffer for hex view of string, including '0x' prefix,
2354 2 hex chars / byte and trailing 0
2355 */
2356 16 const int buff_len = 2 + (256 * 2) + 1;
2357 char buff[buff_len];
2358
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 str_to_hex(buff, (const char *)&(ndb_info[EXTRA_ROW_INFO_HEADER_LENGTH]),
2359 extra_row_ndb_info_payload_len);
2360
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 my_b_printf(file, "data: %s\n", buff);
2361 }
2362
2363
2/2
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 3249 times.
3354 if (m_extra_row_info.have_part()) {
2364
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 73 times.
105 if (general_type_code == binary_log::UPDATE_ROWS_EVENT) {
2365
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 my_b_printf(file,
2366 "### Extra row info for partitioning: source_partition: %d"
2367 " target_partition: %d",
2368 32 m_extra_row_info.get_source_partition_id(),
2369 32 m_extra_row_info.get_partition_id());
2370 } else
2371
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 my_b_printf(file, "### Extra row info for partitioning: partition: %u",
2372 73 m_extra_row_info.get_partition_id());
2373
1/2
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
105 my_b_printf(file, "\n");
2374 }
2375
2376
3/4
✓ Branch 0 taken 536 times.
✓ Branch 1 taken 255 times.
✓ Branch 2 taken 2563 times.
✗ Branch 3 not taken.
3354 switch (general_type_code) {
2377 536 case binary_log::WRITE_ROWS_EVENT:
2378 536 sql_command = "INSERT INTO";
2379 536 sql_clause1 = "### SET\n";
2380 536 sql_clause2 = nullptr;
2381 536 break;
2382 255 case binary_log::DELETE_ROWS_EVENT:
2383 255 sql_command = "DELETE FROM";
2384 255 sql_clause1 = "### WHERE\n";
2385 255 sql_clause2 = nullptr;
2386 255 break;
2387 2563 case binary_log::UPDATE_ROWS_EVENT:
2388 case binary_log::PARTIAL_UPDATE_ROWS_EVENT:
2389 2563 sql_command = "UPDATE";
2390 2563 sql_clause1 = "### WHERE\n";
2391 2563 sql_clause2 = "### SET\n";
2392 2563 break;
2393 default:
2394 sql_command = sql_clause1 = sql_clause2 = nullptr;
2395 assert(0); /* Not possible */
2396 }
2397
2398
3/6
✓ Branch 0 taken 3354 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3354 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3354 times.
6708 if (!(map = print_event_info->m_table_map.get_table(m_table_id)) ||
2399
2/4
✓ Branch 0 taken 3354 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3354 times.
3354 !(td = map->create_table_def())) {
2400 char llbuff[22];
2401 my_b_printf(file, "### Row event for unknown table #%s",
2402 llstr(m_table_id, llbuff));
2403 return;
2404 }
2405
2406 /* If the write rows event contained no values for the AI */
2407
2/2
✓ Branch 0 taken 536 times.
✓ Branch 1 taken 2818 times.
3354 if (((general_type_code == binary_log::WRITE_ROWS_EVENT) &&
2408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 536 times.
536 (m_rows_buf == m_rows_end))) {
2409 my_b_printf(file, "### INSERT INTO `%s`.`%s` VALUES ()\n",
2410 map->get_db_name(), map->get_table_name());
2411 goto end;
2412 }
2413
2414
2/2
✓ Branch 0 taken 4239 times.
✓ Branch 1 taken 3354 times.
7593 for (const uchar *value = m_rows_buf; value < m_rows_end;) {
2415 size_t length;
2416 quoted_db_len =
2417
1/2
✓ Branch 0 taken 4239 times.
✗ Branch 1 not taken.
4239 my_strmov_quoted_identifier((char *)quoted_db, map->get_db_name());
2418
1/2
✓ Branch 0 taken 4239 times.
✗ Branch 1 not taken.
4239 quoted_table_len = my_strmov_quoted_identifier((char *)quoted_table,
2419 map->get_table_name());
2420 4239 quoted_db[quoted_db_len] = '\0';
2421 4239 quoted_table[quoted_table_len] = '\0';
2422
1/2
✓ Branch 0 taken 4239 times.
✗ Branch 1 not taken.
4239 my_b_printf(file, "### %s %s.%s\n", sql_command, quoted_db, quoted_table);
2423 /* Print the first image */
2424
2/4
✓ Branch 0 taken 4239 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4239 times.
4239 if (!(length = print_verbose_one_row(file, td, print_event_info, &m_cols,
2425 value, (const uchar *)sql_clause1,
2426 row_image_type)))
2427 goto end;
2428 4239 value += length;
2429
2430 /* Print the second image (for UPDATE only) */
2431
2/2
✓ Branch 0 taken 2940 times.
✓ Branch 1 taken 1299 times.
4239 if (sql_clause2) {
2432
2/4
✓ Branch 0 taken 2940 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2940 times.
2940 if (!(length = print_verbose_one_row(
2433 file, td, print_event_info, &m_cols_ai, value,
2434 (const uchar *)sql_clause2, enum_row_image_type::UPDATE_AI)))
2435 goto end;
2436 2940 value += length;
2437 }
2438 }
2439
2440 3354 end:
2441
1/2
✓ Branch 0 taken 3354 times.
✗ Branch 1 not taken.
3354 delete td;
2442 }
2443
2444 64234 void Log_event::print_base64(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info,
2445 bool more) const {
2446 64234 const uchar *ptr = (const uchar *)temp_buf;
2447 64234 uint32 size = uint4korr(ptr + EVENT_LEN_OFFSET);
2448
1/2
✓ Branch 0 taken 64234 times.
✗ Branch 1 not taken.
64234 DBUG_TRACE;
2449
2450 64234 uint64 const tmp_str_sz = base64_needed_encoded_length((uint64)size);
2451 char *const tmp_str =
2452
1/2
✓ Branch 0 taken 64234 times.
✗ Branch 1 not taken.
64234 (char *)my_malloc(key_memory_log_event, tmp_str_sz, MYF(MY_WME));
2453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64234 times.
64234 if (!tmp_str) {
2454 fprintf(stderr,
2455 "\nError: Out of memory. "
2456 "Could not print correct binlog event.\n");
2457 return;
2458 }
2459
2460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64234 times.
64234 if (base64_encode(ptr, (size_t)size, tmp_str)) {
2461 assert(0);
2462 }
2463
2464
2/2
✓ Branch 0 taken 63084 times.
✓ Branch 1 taken 1150 times.
64234 if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS) {
2465
3/4
✓ Branch 0 taken 29216 times.
✓ Branch 1 taken 33868 times.
✓ Branch 2 taken 29216 times.
✗ Branch 3 not taken.
63084 if (my_b_tell(file) == 0) my_b_printf(file, "\nBINLOG '\n");
2466
2467
1/2
✓ Branch 0 taken 63084 times.
✗ Branch 1 not taken.
63084 my_b_printf(file, "%s\n", tmp_str);
2468
2469
3/4
✓ Branch 0 taken 33452 times.
✓ Branch 1 taken 29632 times.
✓ Branch 2 taken 33452 times.
✗ Branch 3 not taken.
63084 if (!more) my_b_printf(file, "'%s\n", print_event_info->delimiter);
2470 }
2471
2472
2/2
✓ Branch 0 taken 9408 times.
✓ Branch 1 taken 54826 times.
64234 if (print_event_info->verbose) {
2473 9408 Rows_log_event *ev = nullptr;
2474 9408 Log_event_type et = (Log_event_type)ptr[EVENT_TYPE_OFFSET];
2475
2476 9408 enum_binlog_checksum_alg ev_checksum_alg = common_footer->checksum_alg;
2477 Format_description_event fd_evt =
2478
1/2
✓ Branch 0 taken 9408 times.
✗ Branch 1 not taken.
9408 Format_description_event(BINLOG_VERSION, server_version);
2479 9408 fd_evt.footer()->checksum_alg = ev_checksum_alg;
2480
2481
5/5
✓ Branch 0 taken 3306 times.
✓ Branch 1 taken 537 times.
✓ Branch 2 taken 255 times.
✓ Branch 3 taken 2563 times.
✓ Branch 4 taken 2747 times.
9408 switch (et) {
2482 3306 case binary_log::TABLE_MAP_EVENT: {
2483 Table_map_log_event *map;
2484
2/4
✓ Branch 0 taken 3306 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3306 times.
✗ Branch 3 not taken.
3306 map = new Table_map_log_event((const char *)ptr, &fd_evt);
2485
1/2
✓ Branch 0 taken 3306 times.
✗ Branch 1 not taken.
3306 print_event_info->m_table_map.set_table(map->get_table_id(), map);
2486 3306 break;
2487 }
2488 537 case binary_log::WRITE_ROWS_EVENT:
2489 case binary_log::WRITE_ROWS_EVENT_V1: {
2490
2/4
✓ Branch 0 taken 537 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 537 times.
✗ Branch 3 not taken.
537 ev = new Write_rows_log_event((const char *)ptr, &fd_evt);
2491 537 break;
2492 }
2493 255 case binary_log::DELETE_ROWS_EVENT:
2494 case binary_log::DELETE_ROWS_EVENT_V1: {
2495
2/4
✓ Branch 0 taken 255 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 255 times.
✗ Branch 3 not taken.
255 ev = new Delete_rows_log_event((const char *)ptr, &fd_evt);
2496 255 break;
2497 }
2498 2563 case binary_log::UPDATE_ROWS_EVENT:
2499 case binary_log::UPDATE_ROWS_EVENT_V1:
2500 case binary_log::PARTIAL_UPDATE_ROWS_EVENT: {
2501
2/4
✓ Branch 0 taken 2563 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2563 times.
✗ Branch 3 not taken.
2563 ev = new Update_rows_log_event((const char *)ptr, &fd_evt);
2502 2563 break;
2503 }
2504 2747 default:
2505 2747 break;
2506 }
2507
2508
2/2
✓ Branch 0 taken 3355 times.
✓ Branch 1 taken 6053 times.
9408 if (ev) {
2509
1/2
✓ Branch 0 taken 3355 times.
✗ Branch 1 not taken.
3355 ev->print_verbose(&print_event_info->footer_cache, print_event_info);
2510
1/2
✓ Branch 0 taken 3355 times.
✗ Branch 1 not taken.
3355 delete ev;
2511 }
2512 9408 }
2513
2514
1/2
✓ Branch 0 taken 64234 times.
✗ Branch 1 not taken.
64234 my_free(tmp_str);
2515
1/2
✓ Branch 0 taken 64234 times.
✗ Branch 1 not taken.
64234 }
2516
2517 /*
2518 Log_event::print_timestamp()
2519 */
2520
2521 186031 void Log_event::print_timestamp(IO_CACHE *file, time_t *ts) const {
2522 struct tm *res;
2523 /*
2524 In some Windows versions timeval.tv_sec is defined as "long",
2525 not as "time_t" and can be of a different size.
2526 Let's use a temporary time_t variable to execute localtime()
2527 with a correct argument type.
2528 */
2529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 186031 times.
186031 time_t ts_tmp = ts ? *ts : (ulong)common_header->when.tv_sec;
2530
1/2
✓ Branch 0 taken 186031 times.
✗ Branch 1 not taken.
186031 DBUG_TRACE;
2531 struct tm tm_tmp;
2532 186031 localtime_r(&ts_tmp, (res = &tm_tmp));
2533 186031 my_b_printf(file, "%02d%02d%02d %2d:%02d:%02d", res->tm_year % 100,
2534
1/2
✓ Branch 0 taken 186031 times.
✗ Branch 1 not taken.
186031 res->tm_mon + 1, res->tm_mday, res->tm_hour, res->tm_min,
2535 res->tm_sec);
2536 186031 }
2537
2538 #endif /* !MYSQL_SERVER */
2539
2540 #if defined(MYSQL_SERVER)
2541 662477 inline Log_event::enum_skip_reason Log_event::continue_group(
2542 Relay_log_info *rli) {
2543
2/2
✓ Branch 0 taken 886 times.
✓ Branch 1 taken 661591 times.
662477 if (rli->slave_skip_counter == 1) return Log_event::EVENT_SKIP_IGNORE;
2544 661591 return Log_event::do_shall_skip(rli);
2545 }
2546
2547 /**
2548 @param end_group_sets_max_dbs when true the group terminal event
2549 can carry partition info, see a note below.
2550 @return true in cases the current event
2551 carries partition data,
2552 false otherwise
2553
2554 @note Some events combination may force to adjust partition info.
2555 In particular BEGIN, BEGIN_LOAD_QUERY_EVENT, COMMIT
2556 where none of the events holds partitioning data
2557 causes the sequential applying of the group through
2558 assigning OVER_MAX_DBS_IN_EVENT_MTS to mts_accessed_dbs
2559 of the group terminator (e.g COMMIT query) event.
2560 */
2561 1562 bool Log_event::contains_partition_info(bool end_group_sets_max_dbs) {
2562 bool res;
2563
2564
3/3
✓ Branch 0 taken 254 times.
✓ Branch 1 taken 773 times.
✓ Branch 2 taken 535 times.
1562 switch (get_type_code()) {
2565 254 case binary_log::TABLE_MAP_EVENT:
2566 case binary_log::EXECUTE_LOAD_QUERY_EVENT:
2567 case binary_log::TRANSACTION_PAYLOAD_EVENT:
2568 254 res = true;
2569
2570 254 break;
2571
2572 773 case binary_log::QUERY_EVENT: {
2573 773 Query_log_event *qev = static_cast<Query_log_event *>(this);
2574
8/8
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 687 times.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 763 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 763 times.
2303 if ((ends_group() && end_group_sets_max_dbs) ||
2575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 763 times.
1530 (qev->is_query_prefix_match(STRING_WITH_LEN("XA COMMIT")) ||
2576 763 qev->is_query_prefix_match(STRING_WITH_LEN("XA ROLLBACK")))) {
2577 10 res = true;
2578 10 qev->mts_accessed_dbs = OVER_MAX_DBS_IN_EVENT_MTS;
2579 } else
2580
4/4
✓ Branch 0 taken 683 times.
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 482 times.
✓ Branch 3 taken 201 times.
763 res = (!ends_group() && !starts_group()) ? true : false;
2581 773 break;
2582 }
2583 535 default:
2584 535 res = false;
2585 }
2586
2587 1562 return res;
2588 }
2589 /*
2590 SYNOPSIS
2591 This function assigns a parent ID to the job group being scheduled in
2592 parallel. It also checks if we can schedule the new event in parallel with the
2593 previous ones being executed.
2594
2595 @param ev log event that has to be scheduled next.
2596 @param rli Pointer to coordinator's relay log info.
2597 @return true if error
2598 false otherwise
2599 */
2600 327832 static bool schedule_next_event(Log_event *ev, Relay_log_info *rli) {
2601 int error;
2602 // Check if we can schedule this event
2603 327832 error = rli->current_mts_submode->schedule_next_event(rli, ev);
2604
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 327741 times.
327820 switch (error) {
2605 char llbuff[22];
2606 1 case ER_MTS_CANT_PARALLEL:
2607
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 llstr(rli->get_event_relay_log_pos(), llbuff);
2608
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 my_error(ER_MTS_CANT_PARALLEL, MYF(0), ev->get_type_str(),
2609 rli->get_event_relay_log_name(), llbuff,
2610 "The master event is logically timestamped incorrectly.");
2611 1 return true;
2612 8 case ER_MTS_INCONSISTENT_DATA:
2613
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
8 llstr(rli->get_event_relay_log_pos(), llbuff);
2614 {
2615 7 char errfmt[] =
2616 "Coordinator experienced an error or was killed while scheduling "
2617 "an event at relay-log name %s position %s.";
2618 char errbuf[sizeof(errfmt) + FN_REFLEN + sizeof(llbuff)];
2619 7 sprintf(errbuf, errfmt, rli->get_event_relay_log_name(), llbuff);
2620
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_error(ER_MTS_INCONSISTENT_DATA, MYF(0), errbuf);
2621 7 return true;
2622 }
2623 /* Don't have to do anything. */
2624 return true;
2625 70 case -1:
2626 /* Unable to schedule: wait_for_last_committed_trx has failed */
2627 70 return true;
2628 327741 default:
2629 327741 return false;
2630 }
2631 /* Keep compiler happy */
2632 return false;
2633 }
2634
2635 /**
2636 The method maps the event to a Worker and return a pointer to it.
2637 Sending the event to the Worker is done by the caller.
2638
2639 Irrespective of the type of Group marking (DB partitioned or BGC) the
2640 following holds true:
2641
2642 - recognize the beginning of a group to allocate the group descriptor
2643 and queue it;
2644 - associate an event with a Worker (which also handles possible conflicts
2645 detection and waiting for their termination);
2646 - finalize the group assignment when the group closing event is met.
2647
2648 When parallelization mode is BGC-based the partitioning info in the event
2649 is simply ignored. Thereby association with a Worker does not require
2650 Assigned Partition Hash of the partitioned method.
2651 This method is not interested in all the taxonomy of the event group
2652 property, what we care about is the boundaries of the group.
2653
2654 As a part of the group, an event belongs to one of the following types:
2655
2656 B - beginning of a group of events (BEGIN query_log_event)
2657 g - mini-group representative event containing the partition info
2658 (any Table_map, a Query_log_event)
2659 p - a mini-group internal event that *p*receding its g-parent
2660 (int_, rand_, user_ var:s)
2661 r - a mini-group internal "regular" event that follows its g-parent
2662 (Delete, Update, Write -rows)
2663 T - terminator of the group (XID, COMMIT, ROLLBACK, auto-commit query)
2664
2665 Only the first g-event computes the assigned Worker which once
2666 is determined remains to be for the rest of the group.
2667 That is the g-event solely carries partitioning info.
2668 For B-event the assigned Worker is NULL to indicate Coordinator
2669 has not yet decided. The same applies to p-event.
2670
2671 Notice, these is a special group consisting of optionally multiple p-events
2672 terminating with a g-event.
2673 Such case is caused by old master binlog and a few corner-cases of
2674 the current master version (todo: to fix).
2675
2676 In case of the event accesses more than OVER_MAX_DBS the method
2677 has to ensure sure previously assigned groups to all other workers are
2678 done.
2679
2680
2681 @note The function updates GAQ queue directly, updates APH hash
2682 plus relocates some temporary tables from Coordinator's list into
2683 involved entries of APH through @c map_db_to_worker.
2684 There's few memory allocations commented where to be freed.
2685
2686 @return a pointer to the Worker struct or NULL.
2687 */
2688
2689 1723429 Slave_worker *Log_event::get_slave_worker(Relay_log_info *rli) {
2690 1723429 Slave_job_group group = Slave_job_group(), *ptr_group = nullptr;
2691 bool is_s_event;
2692 1723429 Slave_worker *ret_worker = nullptr;
2693 char llbuff[22];
2694 1723429 Slave_committed_queue *gaq = rli->gaq;
2695
1/2
✓ Branch 0 taken 1723429 times.
✗ Branch 1 not taken.
1723429 DBUG_TRACE;
2696
2697 /* checking partitioning properties and perform corresponding actions */
2698
2699 // Beginning of a group designated explicitly with BEGIN or GTID
2700
7/8
✓ Branch 0 taken 1723429 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1434349 times.
✓ Branch 3 taken 289080 times.
✓ Branch 4 taken 1106646 times.
✓ Branch 5 taken 327703 times.
✓ Branch 6 taken 616912 times.
✓ Branch 7 taken 1106517 times.
2830075 if ((is_s_event = starts_group()) || is_gtid_event(this) ||
2701 // or DDL:s or autocommit queries possibly associated with own p-events
2702
4/4
✓ Branch 0 taken 38645 times.
✓ Branch 1 taken 1068001 times.
✓ Branch 2 taken 129 times.
✓ Branch 3 taken 38516 times.
1106646 (!rli->curr_group_seen_begin && !rli->curr_group_seen_gtid &&
2703 /*
2704 the following is a special case of B-free still multi-event group like
2705 { p_1,p_2,...,p_k, g }.
2706 In that case either GAQ is empty (the very first group is being
2707 assigned) or the last assigned group index points at one of
2708 mapped-to-a-worker.
2709 */
2710
3/4
✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
✓ Branch 3 taken 9 times.
129 (gaq->empty() ||
2711
2/4
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
120 gaq->get_job_group(rli->gaq->assigned_group_index)->worker_id !=
2712 MTS_WORKER_UNDEF))) {
2713
3/4
✓ Branch 0 taken 327832 times.
✓ Branch 1 taken 289080 times.
✓ Branch 2 taken 327832 times.
✗ Branch 3 not taken.
616912 if (!rli->curr_group_seen_gtid && !rli->curr_group_seen_begin) {
2714 327832 rli->mts_groups_assigned++;
2715
2716 327832 rli->curr_group_isolated = false;
2717 327832 group.reset(common_header->log_pos, rli->mts_groups_assigned);
2718 // the last occupied GAQ's array index
2719
1/2
✓ Branch 0 taken 327832 times.
✗ Branch 1 not taken.
327832 gaq->assigned_group_index = gaq->en_queue(&group);
2720
3/8
✓ Branch 0 taken 327832 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 327832 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 327832 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
327832 DBUG_PRINT("info", ("gaq_idx= %ld gaq->size=%zu",
2721 gaq->assigned_group_index, gaq->capacity));
2722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 327832 times.
327832 assert(gaq->assigned_group_index != MTS_WORKER_UNDEF);
2723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 327832 times.
327832 assert(gaq->assigned_group_index < gaq->capacity);
2724
2/4
✓ Branch 0 taken 327832 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 327832 times.
327832 assert(gaq->get_job_group(rli->gaq->assigned_group_index)
2725 ->group_relay_log_name == nullptr);
2726
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 327832 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
327832 assert(rli->last_assigned_worker == nullptr ||
2727 !is_mts_db_partitioned(rli));
2728
2729
5/6
✓ Branch 0 taken 327832 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 327703 times.
✓ Branch 3 taken 129 times.
✓ Branch 4 taken 327703 times.
✓ Branch 5 taken 129 times.
327832 if (is_s_event || is_gtid_event(this)) {
2730 327703 Slave_job_item job_item = {this, rli->get_event_relay_log_number(),
2731 327703 rli->get_event_start_pos()};
2732 // B-event is appended to the Deferred Array associated with GCAP
2733
1/2
✓ Branch 0 taken 327703 times.
✗ Branch 1 not taken.
327703 rli->curr_group_da.push_back(job_item);
2734
2735
2/4
✓ Branch 0 taken 327703 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 327703 times.
327703 assert(rli->curr_group_da.size() == 1);
2736
2737
2/4
✓ Branch 0 taken 327703 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 327703 times.
327703 if (starts_group()) {
2738 // mark the current group as started with explicit B-event
2739 rli->mts_end_group_sets_max_dbs = true;
2740 rli->curr_group_seen_begin = true;
2741 }
2742
2743
1/2
✓ Branch 0 taken 327703 times.
✗ Branch 1 not taken.
327703 if (is_gtid_event(this)) {
2744 // mark the current group as started with explicit Gtid-event
2745 327703 rli->curr_group_seen_gtid = true;
2746
2747 327703 Gtid_log_event *gtid_log_ev = static_cast<Gtid_log_event *>(this);
2748
1/2
✓ Branch 0 taken 327703 times.
✗ Branch 1 not taken.
327703 rli->started_processing(gtid_log_ev);
2749 }
2750
2751
3/4
✓ Branch 0 taken 327691 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 327615 times.
327703 if (schedule_next_event(this, rli)) {
2752 76 rli->abort_slave = true;
2753
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 if (is_gtid_event(this)) {
2754
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 rli->clear_processing_trx();
2755 }
2756 76 return nullptr;
2757 }
2758 327615 return ret_worker;
2759 }
2760 129 } else {
2761 /*
2762 The block is a result of not making GTID event as group starter.
2763 TODO: Make GITD event as B-event that is starts_group() to
2764 return true.
2765 */
2766 289080 Slave_job_item job_item = {this, rli->get_event_relay_log_number(),
2767 289080 rli->get_event_relay_log_pos()};
2768
2769 // B-event is appended to the Deferred Array associated with GCAP
2770
1/2
✓ Branch 0 taken 289080 times.
✗ Branch 1 not taken.
289080 rli->curr_group_da.push_back(job_item);
2771 289080 rli->curr_group_seen_begin = true;
2772 289080 rli->mts_end_group_sets_max_dbs = true;
2773
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 289080 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 289080 times.
289080 if (!rli->curr_group_seen_gtid && schedule_next_event(this, rli)) {
2774 rli->abort_slave = true;
2775 return nullptr;
2776 }
2777
2778
2/4
✓ Branch 0 taken 289080 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 289080 times.
289080 assert(rli->curr_group_da.size() == 2);
2779
2/4
✓ Branch 0 taken 289080 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 289080 times.
289080 assert(starts_group());
2780 289080 return ret_worker;
2781 }
2782
3/4
✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 127 times.
129 if (schedule_next_event(this, rli)) {
2783 2 rli->abort_slave = true;
2784 2 return nullptr;
2785 }
2786 }
2787
2788
1/2
✓ Branch 0 taken 1106644 times.
✗ Branch 1 not taken.
1106644 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
2789
3/4
✓ Branch 0 taken 1106644 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1106021 times.
✓ Branch 3 taken 623 times.
1106644 if (!is_mts_db_partitioned(rli)) {
2790 /* Get least occupied worker */
2791
1/2
✓ Branch 0 taken 1106021 times.
✗ Branch 1 not taken.
1106021 ret_worker = rli->current_mts_submode->get_least_occupied_worker(
2792 rli, &rli->workers, this);
2793
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1106020 times.
1106021 if (ret_worker == nullptr) {
2794 /* get_least_occupied_worker may return NULL if the thread is killed */
2795 1 Slave_job_item job_item = {this, rli->get_event_relay_log_number(),
2796 1 rli->get_event_start_pos()};
2797
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->curr_group_da.push_back(job_item);
2798
2799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(thd->killed);
2800 1 return nullptr;
2801 }
2802 1106020 ptr_group->worker_id = ret_worker->id;
2803
3/4
✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 336 times.
✓ Branch 3 taken 287 times.
623 } else if (contains_partition_info(rli->mts_end_group_sets_max_dbs)) {
2804 336 int i = 0;
2805 336 Mts_db_names mts_dbs;
2806
2807
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 get_mts_dbs(&mts_dbs, rli->rpl_filter);
2808 /*
2809 Bug 12982188 - MTS: SBR ABORTS WITH ERROR 1742 ON LOAD DATA
2810 Logging on master can create a group with no events holding
2811 the partition info.
2812 The following assert proves there's the only reason
2813 for such group.
2814 */
2815 #ifndef NDEBUG
2816 {
2817 556 bool empty_group_with_gtids = rli->curr_group_seen_begin &&
2818
6/8
✓ Branch 0 taken 220 times.
✓ Branch 1 taken 116 times.
✓ Branch 2 taken 220 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 220 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 217 times.
336 rli->curr_group_seen_gtid && ends_group();
2819
2820 bool begin_load_query_event =
2821
2/4
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
339 ((rli->curr_group_da.size() == 3 && rli->curr_group_seen_gtid) ||
2822
7/10
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 333 times.
✓ Branch 2 taken 333 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 174 times.
✓ Branch 5 taken 159 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 174 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
339 (rli->curr_group_da.size() == 2 && !rli->curr_group_seen_gtid)) &&
2823
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 (rli->curr_group_da.back().data->get_type_code() ==
2824 336 binary_log::BEGIN_LOAD_QUERY_EVENT);
2825
2826 bool delete_file_event =
2827
1/4
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
336 ((rli->curr_group_da.size() == 4 && rli->curr_group_seen_gtid) ||
2828
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
✓ Branch 2 taken 336 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 333 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
336 (rli->curr_group_da.size() == 3 && !rli->curr_group_seen_gtid)) &&
2829 (rli->curr_group_da.back().data->get_type_code() ==
2830 336 binary_log::DELETE_FILE_EVENT);
2831
2832
8/18
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 329 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
336 assert((!ends_group() ||
2833 (get_type_code() == binary_log::TRANSACTION_PAYLOAD_EVENT) ||
2834 (get_type_code() == binary_log::QUERY_EVENT &&
2835 static_cast<Query_log_event *>(this)->is_query_prefix_match(
2836 STRING_WITH_LEN("XA ROLLBACK")))) ||
2837 empty_group_with_gtids ||
2838 (rli->mts_end_group_sets_max_dbs &&
2839 (begin_load_query_event || delete_file_event)));
2840 }
2841 #endif
2842
2843 // partitioning info is found which drops the flag
2844 336 rli->mts_end_group_sets_max_dbs = false;
2845 336 ret_worker = rli->last_assigned_worker;
2846
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 308 times.
336 if (mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS) {
2847 // Worker with id 0 to handle serial execution
2848
2/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
28 if (!ret_worker) ret_worker = rli->workers.at(0);
2849 // No need to know a possible error out of synchronization call.
2850
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 (void)rli->current_mts_submode->wait_for_workers_to_finish(rli,
2851 ret_worker);
2852 /*
2853 this marking is transferred further into T-event of the current group.
2854 */
2855 28 rli->curr_group_isolated = true;
2856 }
2857 #ifndef NDEBUG
2858 {
2859
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 std::ostringstream oss;
2860 672 for (i = 0;
2861
4/4
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 336 times.
✓ Branch 3 taken 336 times.
672 i < ((mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS) ? mts_dbs.num : 1);
2862 i++) {
2863
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 28 times.
336 if (mts_dbs.name[i] != nullptr) {
2864
2/4
✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 308 times.
✗ Branch 3 not taken.
308 oss << mts_dbs.name[i] << ", ";
2865 }
2866 }
2867
3/12
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 336 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 336 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
336 DBUG_PRINT("debug", ("ASSIGN %p %s", current_thd, oss.str().c_str()));
2868 336 }
2869 #endif
2870
2871 /* One run of the loop in the case of over-max-db:s */
2872 672 for (i = 0;
2873
4/4
✓ Branch 0 taken 616 times.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 336 times.
✓ Branch 3 taken 336 times.
672 i < ((mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS) ? mts_dbs.num : 1);
2874 i++) {
2875 /*
2876 The over max db:s case handled through passing to map_db_to_worker
2877 such "all" db as encoded as the "" empty string.
2878 Note, the empty string is allocated in a large buffer
2879 to satisfy hashcmp() implementation.
2880 */
2881 336 const char all_db[NAME_LEN] = {0};
2882
2/4
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 336 times.
336 if (!(ret_worker = map_db_to_worker(
2883
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 308 times.
336 mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS ? all_db
2884 : mts_dbs.name[i],
2885 rli, &mts_assigned_partitions[i],
2886 /*
2887 todo: optimize it. Although pure
2888 rows- event load in insensitive to the flag value
2889 */
2890 true, ret_worker))) {
2891 llstr(rli->get_event_relay_log_pos(), llbuff);
2892 my_error(ER_MTS_CANT_PARALLEL, MYF(0), get_type_str(),
2893 rli->get_event_relay_log_name(), llbuff,
2894 "could not distribute the event to a Worker");
2895 return ret_worker;
2896 }
2897 // all temporary tables are transferred from Coordinator in over-max case
2898
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 308 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
336 assert(mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS ||
2899 !thd->temporary_tables);
2900
3/4
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 336 times.
336 assert(!strcmp(
2901 mts_assigned_partitions[i]->db,
2902 mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS ? mts_dbs.name[i] : all_db));
2903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
336 assert(ret_worker == mts_assigned_partitions[i]->worker);
2904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
336 assert(mts_assigned_partitions[i]->usage >= 0);
2905 }
2906
2907
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 if ((ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index))
2908
2/2
✓ Branch 0 taken 287 times.
✓ Branch 1 taken 49 times.
336 ->worker_id == MTS_WORKER_UNDEF) {
2909 287 ptr_group->worker_id = ret_worker->id;
2910
2911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 287 times.
287 assert(ptr_group->group_relay_log_name == nullptr);
2912 }
2913
2914
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 308 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
336 assert(i == mts_dbs.num || mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS);
2915 } else {
2916 // a mini-group internal "regular" event
2917
2/2
✓ Branch 0 taken 278 times.
✓ Branch 1 taken 9 times.
287 if (rli->last_assigned_worker) {
2918 278 ret_worker = rli->last_assigned_worker;
2919
2920
2/6
✓ Branch 0 taken 278 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 278 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
278 assert(rli->curr_group_assigned_parts.size() > 0 || ret_worker->id == 0);
2921 } else // int_, rand_, user_ var:s, load-data events
2922 {
2923
4/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
25 if (!(get_type_code() == binary_log::INTVAR_EVENT ||
2924
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
16 get_type_code() == binary_log::RAND_EVENT ||
2925
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
10 get_type_code() == binary_log::USER_VAR_EVENT ||
2926
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 get_type_code() == binary_log::BEGIN_LOAD_QUERY_EVENT ||
2927
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 get_type_code() == binary_log::APPEND_BLOCK_EVENT ||
2928 3 get_type_code() == binary_log::DELETE_FILE_EVENT ||
2929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 is_ignorable_event())) {
2930 assert(!ret_worker);
2931
2932 llstr(rli->get_event_relay_log_pos(), llbuff);
2933 my_error(ER_MTS_CANT_PARALLEL, MYF(0), get_type_str(),
2934 rli->get_event_relay_log_name(), llbuff,
2935 "the event is a part of a group that is unsupported in "
2936 "the parallel execution mode");
2937
2938 return ret_worker;
2939 }
2940 /*
2941 In the logical clock scheduler any internal gets scheduled directly.
2942 That is Int_var, @User_var and Rand bypass the deferred array.
2943 Their association with relay-log physical coordinates is provided
2944 by the same mechanism that applies to a regular event.
2945 */
2946 9 Slave_job_item job_item = {this, rli->get_event_relay_log_number(),
2947 9 rli->get_event_start_pos()};
2948
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 rli->curr_group_da.push_back(job_item);
2949
2950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 assert(!ret_worker);
2951 9 return ret_worker;
2952 }
2953 }
2954
2955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1106634 times.
1106634 assert(ret_worker);
2956 // T-event: Commit, Xid, a DDL query or dml query of B-less group.4
2957
2958 /*
2959 Preparing event physical coordinates info for Worker before any
2960 event got scheduled so when Worker error-stopped at the first
2961 event it would be aware of where exactly in the event stream.
2962 */
2963
2/2
✓ Branch 0 taken 31321 times.
✓ Branch 1 taken 1075313 times.
1106634 if (!ret_worker->master_log_change_notified) {
2964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31321 times.
31321 if (!ptr_group)
2965 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
2966
1/2
✓ Branch 0 taken 31321 times.
✗ Branch 1 not taken.
31321 ptr_group->group_master_log_name = my_strdup(
2967 key_memory_log_event, rli->get_group_master_log_name(), MYF(MY_WME));
2968 31321 ret_worker->master_log_change_notified = true;
2969
2970
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31321 times.
31321 assert(!ptr_group->notified);
2971 #ifndef NDEBUG
2972 31321 ptr_group->notified = true;
2973 #endif
2974 }
2975
2976 /* Notify the worker about new FD */
2977
2/2
✓ Branch 0 taken 11452 times.
✓ Branch 1 taken 1095182 times.
1106634 if (!ret_worker->fd_change_notified) {
2978
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11452 times.
11452 if (!ptr_group)
2979 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
2980 /*
2981 Increment the usage counter on behalf of Worker.
2982 This avoids inadvertent FD deletion in a race case where Coordinator
2983 would install a next new FD before Worker has noticed the previous one.
2984 */
2985 11452 ++rli->get_rli_description_event()->atomic_usage_counter;
2986 11452 ptr_group->new_fd_event = rli->get_rli_description_event();
2987 11452 ret_worker->fd_change_notified = true;
2988 }
2989
2990
5/6
✓ Branch 0 taken 1106634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 817541 times.
✓ Branch 3 taken 289093 times.
✓ Branch 4 taken 327613 times.
✓ Branch 5 taken 779021 times.
1924175 if (ends_group() ||
2991
4/4
✓ Branch 0 taken 38545 times.
✓ Branch 1 taken 778996 times.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 38487 times.
856086 (!rli->curr_group_seen_begin &&
2992 38545 (get_type_code() == binary_log::QUERY_EVENT ||
2993 /*
2994 When applying an old binary log without Gtid_log_event and
2995 Anonymous_gtid_log_event, the logic of multi-threaded slave
2996 still need to require that an event (for example, Query_log_event,
2997 User_var_log_event, Intvar_log_event, and Rand_log_event) that
2998 appeared outside of BEGIN...COMMIT was treated as a transaction
2999 of its own. This was just a technicality in the code and did not
3000 cause a problem, since the event and the following Query_log_event
3001 would both be assigned to dedicated worker 0.
3002 */
3003
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 25 times.
58 !rli->curr_group_seen_gtid))) {
3004 327613 rli->mts_group_status = Relay_log_info::MTS_END_GROUP;
3005
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 327585 times.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
327613 if (rli->curr_group_isolated) set_mts_isolate_group();
3006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 327613 times.
327613 if (!ptr_group)
3007 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
3008
3009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 327613 times.
327613 assert(ret_worker != nullptr);
3010
3011 // coordinator has ended buffering this group, update monitoring info
3012
3/4
✓ Branch 0 taken 327613 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 327486 times.
✓ Branch 3 taken 127 times.
327613 if (rli->is_processing_trx()) {
3013
7/12
✓ Branch 0 taken 327486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 327476 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 10 times.
327486 DBUG_EXECUTE_IF("rpl_ps_tables", {
3014 const char act[] =
3015 "now SIGNAL signal.rpl_ps_tables_process_before "
3016 "WAIT_FOR signal.rpl_ps_tables_process_finish";
3017 assert(opt_debug_sync_timeout > 0);
3018 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
3019 };);
3020
1/2
✓ Branch 0 taken 327486 times.
✗ Branch 1 not taken.
327486 rli->finished_processing();
3021
7/12
✓ Branch 0 taken 327486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 327476 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 10 times.
327486 DBUG_EXECUTE_IF("rpl_ps_tables", {
3022 const char act[] =
3023 "now SIGNAL signal.rpl_ps_tables_process_after_finish "
3024 "WAIT_FOR signal.rpl_ps_tables_process_continue";
3025 assert(opt_debug_sync_timeout > 0);
3026 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
3027 };);
3028 }
3029
3030 /*
3031 The following two blocks are executed if the worker has not been
3032 notified about new relay-log or a new checkpoints.
3033 Relay-log string is freed by Coordinator, Worker deallocates
3034 strings in the checkpoint block.
3035 However if the worker exits earlier reclaiming for both happens anyway at
3036 GAQ delete.
3037 */
3038
2/2
✓ Branch 0 taken 31394 times.
✓ Branch 1 taken 296219 times.
327613 if (!ret_worker->relay_log_change_notified) {
3039 /*
3040 Prior this event, C rotated the relay log to drop each
3041 Worker's notified flag. Now group terminating event initiates
3042 the new relay-log (where the current event is from) name
3043 delivery to Worker that will receive it in commit_positions().
3044 */
3045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31394 times.
31394 assert(ptr_group->group_relay_log_name == nullptr);
3046
3047 62788 ptr_group->group_relay_log_name = (char *)my_malloc(
3048
1/2
✓ Branch 0 taken 31394 times.
✗ Branch 1 not taken.
31394 key_memory_log_event, strlen(rli->get_group_relay_log_name()) + 1,
3049 MYF(MY_WME));
3050 31394 strcpy(ptr_group->group_relay_log_name, rli->get_event_relay_log_name());
3051
3052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31394 times.
31394 assert(ptr_group->group_relay_log_name != nullptr);
3053
3054 31394 ret_worker->relay_log_change_notified = true;
3055 }
3056
3057
2/2
✓ Branch 0 taken 192557 times.
✓ Branch 1 taken 135056 times.
327613 if (!ret_worker->checkpoint_notified) {
3058
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 192557 times.
192557 if (!ptr_group)
3059 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
3060
1/2
✓ Branch 0 taken 192557 times.
✗ Branch 1 not taken.
192557 ptr_group->checkpoint_log_name = my_strdup(
3061 key_memory_log_event, rli->get_group_master_log_name(), MYF(MY_WME));
3062 192557 ptr_group->checkpoint_log_pos = rli->get_group_master_log_pos();
3063
1/2
✓ Branch 0 taken 192557 times.
✗ Branch 1 not taken.
192557 ptr_group->checkpoint_relay_log_name = my_strdup(
3064 key_memory_log_event, rli->get_group_relay_log_name(), MYF(MY_WME));
3065 192557 ptr_group->checkpoint_relay_log_pos = rli->get_group_relay_log_pos();
3066 192557 ptr_group->shifted = ret_worker->bitmap_shifted;
3067 192557 ret_worker->bitmap_shifted = 0;
3068 192557 ret_worker->checkpoint_notified = true;
3069 }
3070 327613 ptr_group->checkpoint_seqno = rli->rli_checkpoint_seqno;
3071 327613 ptr_group->ts = common_header->when.tv_sec +
3072 327613 (time_t)exec_time; // Seconds_behind_master related
3073 327613 rli->rli_checkpoint_seqno++;
3074 /*
3075 Coordinator should not use the main memroot however its not
3076 reset elsewhere either, so let's do it safe way.
3077 The main mem root is also reset by the SQL thread in at the end
3078 of applying which Coordinator does not do in this case.
3079 That concludes the memroot reset can't harm anything in SQL thread roles
3080 after Coordinator has finished its current scheduling.
3081 */
3082
1/2
✓ Branch 0 taken 327613 times.
✗ Branch 1 not taken.
327613 thd->mem_root->ClearForReuse();
3083
3084 #ifndef NDEBUG
3085 327613 w_rr++;
3086 #endif
3087 }
3088
3089 1106634 return ret_worker;
3090 1723417 }
3091
3092 7 int Log_event::apply_gtid_event(Relay_log_info *rli) {
3093
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 DBUG_TRACE;
3094
3095 7 int error = 0;
3096
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (rli->curr_group_da.size() < 1) return 1;
3097
3098
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 Log_event *ev = rli->curr_group_da[0].data;
3099
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
7 assert(ev->get_type_code() == binary_log::GTID_LOG_EVENT ||
3100 ev->get_type_code() == binary_log::ANONYMOUS_GTID_LOG_EVENT);
3101
3102
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 error = ev->do_apply_event(rli);
3103 /* Clean up */
3104
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 delete ev;
3105
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 rli->curr_group_da.clear();
3106 7 rli->curr_group_seen_gtid = false;
3107 /*
3108 Removes the job from the (G)lobal (A)ssigned (Q)ueue after
3109 applying it.
3110 */
3111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 assert(rli->gaq->get_length() > 0);
3112 7 Slave_job_group g = Slave_job_group();
3113
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 rli->gaq->de_tail(&g);
3114 /*
3115 The rli->mts_groups_assigned is increased when adding the slave job
3116 generated for the gtid into the (G)lobal (A)ssigned (Q)ueue. So we
3117 decrease it here.
3118 */
3119 7 rli->mts_groups_assigned--;
3120
3121 7 return error;
3122 7 }
3123
3124 /**
3125 Scheduling event to execute in parallel or execute it directly.
3126 In MTS case the event gets associated with either Coordinator or a
3127 Worker. A special case of the association is NULL when the Worker
3128 can't be decided yet. In the single threaded sequential mode the
3129 event maps to SQL thread rli.
3130
3131 @note in case of MTS failure Coordinator destroys all gathered
3132 deferred events.
3133
3134 @return 0 as success, otherwise a failure.
3135 */
3136 1817130 int Log_event::apply_event(Relay_log_info *rli) {
3137
1/2
✓ Branch 0 taken 1817130 times.
✗ Branch 1 not taken.
1817130 DBUG_TRACE;
3138
3/10
✓ Branch 0 taken 1817130 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1817130 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1817130 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1817130 DBUG_PRINT("info", ("event_type=%s", get_type_str()));
3139 1817130 bool parallel = false;
3140 1817130 enum enum_mts_event_exec_mode actual_exec_mode = EVENT_EXEC_PARALLEL;
3141 1817130 THD *rli_thd = rli->info_thd;
3142
3143 1817130 worker = rli;
3144
3145
2/2
✓ Branch 0 taken 1048 times.
✓ Branch 1 taken 1816082 times.
1817130 if (rli->is_mts_recovery()) {
3146
4/4
✓ Branch 0 taken 930 times.
✓ Branch 1 taken 118 times.
✓ Branch 2 taken 894 times.
✓ Branch 3 taken 36 times.
1978 bool skip = bitmap_is_set(&rli->recovery_groups, rli->mts_recovery_index) &&
3147 930 (get_mts_execution_mode(rli->mts_group_status ==
3148 Relay_log_info::MTS_IN_GROUP) ==
3149 1048 EVENT_EXEC_PARALLEL);
3150
2/2
✓ Branch 0 taken 894 times.
✓ Branch 1 taken 154 times.
1048 if (skip) {
3151 894 return 0;
3152 } else {
3153
1/2
✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
154 int error = do_apply_event(rli);
3154
3/4
✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 46 times.
154 if (rli->is_processing_trx()) {
3155 // needed to identify DDL's; uses the same logic as in
3156 // get_slave_worker()
3157
6/8
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 88 times.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
✓ Branch 7 taken 88 times.
108 if (starts_group() && get_type_code() == binary_log::QUERY_EVENT) {
3158 20 rli->curr_group_seen_begin = true;
3159 }
3160
4/4
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 89 times.
215 if (error == 0 &&
3161
5/6
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 58 times.
107 (ends_group() || (get_type_code() == binary_log::QUERY_EVENT &&
3162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 !rli->curr_group_seen_begin))) {
3163
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 rli->finished_processing();
3164 19 rli->curr_group_seen_begin = false;
3165 }
3166 }
3167 154 return error;
3168 }
3169 }
3170
3171
7/8
✓ Branch 0 taken 1816082 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1809181 times.
✓ Branch 3 taken 6901 times.
✓ Branch 4 taken 85752 times.
✓ Branch 5 taken 1723429 times.
✓ Branch 6 taken 92653 times.
✓ Branch 7 taken 1723429 times.
3625263 if (!(parallel = rli->is_parallel_exec()) ||
3172 1809181 ((actual_exec_mode = get_mts_execution_mode(
3173 1809181 rli->mts_group_status == Relay_log_info::MTS_IN_GROUP)) !=
3174 EVENT_EXEC_PARALLEL)) {
3175
2/2
✓ Branch 0 taken 85752 times.
✓ Branch 1 taken 6901 times.
92653 if (parallel) {
3176 /*
3177 There are two classes of events that Coordinator executes
3178 itself. One e.g the master Rotate requires all Workers to finish up
3179 their assignments. The other async class, e.g the slave Rotate,
3180 can't have this such synchronization because Worker might be waiting
3181 for terminal events to finish.
3182 */
3183
3184
2/2
✓ Branch 0 taken 42407 times.
✓ Branch 1 taken 43345 times.
85752 if (actual_exec_mode != EVENT_EXEC_ASYNC) {
3185 /*
3186 this event does not split the current group but is indeed
3187 a separator between two masters' binlogs therefore requiring
3188 Workers to sync.
3189 */
3190
6/12
✓ Branch 0 taken 42407 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 42400 times.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 42407 times.
42407 if (rli->curr_group_da.size() > 0 && is_mts_db_partitioned(rli) &&
3191 get_type_code() != binary_log::INCIDENT_EVENT) {
3192 char llbuff[22];
3193 /*
3194 Possible reason is a old version binlog sequential event
3195 wrappped with BEGIN/COMMIT or preceded by User|Int|Random- var.
3196 MTS has to stop to suggest restart in the permanent sequential
3197 mode.
3198 */
3199 llstr(rli->get_event_relay_log_pos(), llbuff);
3200 my_error(ER_MTS_CANT_PARALLEL, MYF(0), get_type_str(),
3201 rli->get_event_relay_log_name(), llbuff,
3202 "possible malformed group of events from an old master");
3203
3204 /* Coordinator cant continue, it marks MTS group status accordingly
3205 */
3206 rli->mts_group_status = Relay_log_info::MTS_KILLED_GROUP;
3207
3208 goto err;
3209 }
3210
3211 42407 if (get_type_code() == binary_log::INCIDENT_EVENT &&
3212
8/10
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 42399 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
✓ Branch 9 taken 42400 times.
42414 rli->curr_group_da.size() > 0 &&
3213 7 rli->current_mts_submode->get_type() ==
3214 MTS_PARALLEL_TYPE_LOGICAL_CLOCK) {
3215 #ifndef NDEBUG
3216
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 assert(rli->curr_group_da.size() == 1);
3217
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 Log_event *ev = rli->curr_group_da[0].data;
3218
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
7 assert(ev->get_type_code() == binary_log::GTID_LOG_EVENT ||
3219 ev->get_type_code() == binary_log::ANONYMOUS_GTID_LOG_EVENT);
3220 #endif
3221 /*
3222 With MTS logical clock mode, when coordinator is applying an
3223 incident event, it must withdraw delegated_job increased by
3224 the incident's GTID before waiting for workers to finish.
3225 So that it can exit from mta_checkpoint_routine.
3226 */
3227 7 ((Mts_submode_logical_clock *)rli->current_mts_submode)
3228 7 ->withdraw_delegated_job();
3229 }
3230 /*
3231 Marking sure the event will be executed in sequential mode.
3232 */
3233
3/4
✓ Branch 0 taken 42209 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 42201 times.
42407 if (rli->current_mts_submode->wait_for_workers_to_finish(rli) == -1) {
3234 // handle synchronization error
3235
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 rli->report(WARNING_LEVEL, 0,
3236 "Slave worker thread has failed to apply an event. As a "
3237 "consequence, the coordinator thread is stopping "
3238 "execution.");
3239 8 return -1;
3240 }
3241 /*
3242 Given not in-group mark the event handler can invoke checkpoint
3243 update routine in the following course.
3244 */
3245
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 42201 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
42201 assert(rli->mts_group_status == Relay_log_info::MTS_NOT_IN_GROUP ||
3246 !is_mts_db_partitioned(rli));
3247
3248
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 42193 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 42194 times.
42209 if (get_type_code() == binary_log::INCIDENT_EVENT &&
3249
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1 times.
8 rli->curr_group_da.size() > 0) {
3250
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 assert(rli->curr_group_da.size() == 1);
3251 /*
3252 When MTS is enabled, the incident event must be applied by the
3253 coordinator. So the coordinator applies its GTID right before
3254 applying the incident event..
3255 */
3256
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 int error = apply_gtid_event(rli);
3257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (error) return -1;
3258 }
3259
3260 #ifndef NDEBUG
3261 /* all Workers are idle as done through wait_for_workers_to_finish */
3262
2/4
✓ Branch 0 taken 42201 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 42201 times.
42201 for (uint k = 0; k < rli->curr_group_da.size(); k++) {
3263 assert(!(rli->workers[k]->usage_partition));
3264 assert(!(rli->workers[k]->jobs.get_length()));
3265 }
3266 #endif
3267 } else {
3268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43345 times.
43345 assert(actual_exec_mode == EVENT_EXEC_ASYNC);
3269 }
3270 }
3271
3272
1/2
✓ Branch 0 taken 92447 times.
✗ Branch 1 not taken.
92447 int error = do_apply_event(rli);
3273
3/4
✓ Branch 0 taken 92447 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 905 times.
✓ Branch 3 taken 91542 times.
92447 if (rli->is_processing_trx()) {
3274 // needed to identify DDL's; uses the same logic as in get_slave_worker()
3275
6/8
✓ Branch 0 taken 905 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
✓ Branch 3 taken 824 times.
✓ Branch 4 taken 81 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 81 times.
✓ Branch 7 taken 824 times.
905 if (starts_group() && get_type_code() == binary_log::QUERY_EVENT) {
3276 81 rli->curr_group_seen_begin = true;
3277 }
3278
4/4
✓ Branch 0 taken 879 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 111 times.
✓ Branch 3 taken 794 times.
1784 if (error == 0 &&
3279
5/6
✓ Branch 0 taken 879 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 815 times.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 180 times.
✓ Branch 5 taken 635 times.
879 (ends_group() || (get_type_code() == binary_log::QUERY_EVENT &&
3280
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 133 times.
180 !rli->curr_group_seen_begin))) {
3281
2/12
✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 111 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
111 DBUG_EXECUTE_IF("rpl_ps_tables", {
3282 const char act[] =
3283 "now SIGNAL signal.rpl_ps_tables_apply_before "
3284 "WAIT_FOR signal.rpl_ps_tables_apply_finish";
3285 assert(opt_debug_sync_timeout > 0);
3286 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
3287 };);
3288
1/2
✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
111 rli->finished_processing();
3289 111 rli->curr_group_seen_begin = false;
3290
2/12
✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 111 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
111 DBUG_EXECUTE_IF("rpl_ps_tables", {
3291 const char act[] =
3292 "now SIGNAL signal.rpl_ps_tables_apply_after_finish "
3293 "WAIT_FOR signal.rpl_ps_tables_apply_continue";
3294 assert(opt_debug_sync_timeout > 0);
3295 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
3296 };);
3297 }
3298 }
3299 92447 return error;
3300 }
3301
3302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1723429 times.
1723429 assert(actual_exec_mode == EVENT_EXEC_PARALLEL);
3303
9/28
✓ Branch 0 taken 1068001 times.
✓ Branch 1 taken 655428 times.
✓ Branch 2 taken 1068001 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 289001 times.
✓ Branch 5 taken 779000 times.
✓ Branch 6 taken 289001 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 289001 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 289001 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 289001 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
1723429 assert(!(rli->curr_group_seen_begin && ends_group()) ||
3304 /*
3305 This is an empty group being processed due to gtids.
3306 */
3307 (rli->curr_group_seen_begin && rli->curr_group_seen_gtid &&
3308 ends_group()) ||
3309 is_mts_db_partitioned(rli) || rli->last_assigned_worker ||
3310 /*
3311 Begin_load_query can be logged w/o db info and within
3312 Begin/Commit. That's a pattern forcing sequential
3313 applying of LOAD-DATA.
3314 */
3315 (rli->curr_group_da.back().data->get_type_code() ==
3316 binary_log::BEGIN_LOAD_QUERY_EVENT) ||
3317 /*
3318 Delete_file can also be logged w/o db info and within
3319 Begin/Commit. That's a pattern forcing sequential
3320 applying of LOAD-DATA.
3321 */
3322 (rli->curr_group_da.back().data->get_type_code() ==
3323 binary_log::DELETE_FILE_EVENT));
3324
3325 1723429 worker = nullptr;
3326 1723429 rli->mts_group_status = Relay_log_info::MTS_IN_GROUP;
3327
3328 1723417 worker =
3329
1/2
✓ Branch 0 taken 1723417 times.
✗ Branch 1 not taken.
1723429 (Relay_log_info *)(rli->last_assigned_worker = get_slave_worker(rli));
3330
3331 #ifndef NDEBUG
3332
2/2
✓ Branch 0 taken 616783 times.
✓ Branch 1 taken 1106634 times.
1723417 if (rli->last_assigned_worker)
3333
3/8
✓ Branch 0 taken 1106634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1106634 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1106634 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1106634 DBUG_PRINT("mts",
3334 ("Assigning job to worker %lu", rli->last_assigned_worker->id));
3335 #endif
3336
3337 616783 err:
3338
9/10
✓ Branch 0 taken 1723417 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1723409 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 616775 times.
✓ Branch 5 taken 1106634 times.
✓ Branch 6 taken 103 times.
✓ Branch 7 taken 616672 times.
✓ Branch 8 taken 111 times.
✓ Branch 9 taken 1723306 times.
1723417 if (rli_thd->is_error() || (!worker && rli->abort_slave)) {
3339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111 times.
111 assert(!worker);
3340
3341 /*
3342 Destroy all deferred buffered events but the current prior to exit.
3343 The current one will be deleted as an event never destined/assigned
3344 to any Worker in Coordinator's regular execution path.
3345 */
3346
3/4
✓ Branch 0 taken 220 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 109 times.
✓ Branch 3 taken 111 times.
220 for (uint k = 0; k < rli->curr_group_da.size(); k++) {
3347
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
109 Log_event *ev_buf = rli->curr_group_da[k].data;
3348
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
109 if (this != ev_buf) delete ev_buf;
3349 }
3350
1/2
✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
111 rli->curr_group_da.clear();
3351 } else {
3352
4/6
✓ Branch 0 taken 616672 times.
✓ Branch 1 taken 1106634 times.
✓ Branch 2 taken 616672 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 616672 times.
1723306 assert(worker || rli->curr_group_assigned_parts.size() == 0);
3353 }
3354
3355
5/6
✓ Branch 0 taken 1723417 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 616775 times.
✓ Branch 3 taken 1106634 times.
✓ Branch 4 taken 103 times.
✓ Branch 5 taken 616672 times.
3446826 return (!(rli_thd->is_error() || (!worker && rli->abort_slave)) ||
3356
2/4
✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 111 times.
111 DBUG_EVALUATE_IF("fault_injection_get_replica_worker", 1, 0))
3357
2/2
✓ Branch 0 taken 1723409 times.
✓ Branch 1 taken 8 times.
3446834 ? 0
3358 1723417 : -1;
3359 1816920 }
3360
3361 /**************************************************************************
3362 Query_log_event methods
3363 **************************************************************************/
3364
3365 /**
3366 This (which is used only for SHOW BINLOG EVENTS) could be updated to
3367 print SET @@session_var=. But this is not urgent, as SHOW BINLOG EVENTS is
3368 only an information, it does not produce suitable queries to replay (for
3369 example it does not print LOAD DATA INFILE).
3370 @todo
3371 show the catalog ??
3372 */
3373
3374 66125 int Query_log_event::pack_info(Protocol *protocol) {
3375 // TODO: show the catalog ??
3376 66125 String str_buf;
3377 // Add use `DB` to the string if required
3378
5/6
✓ Branch 0 taken 39021 times.
✓ Branch 1 taken 27104 times.
✓ Branch 2 taken 39021 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39013 times.
✓ Branch 5 taken 8 times.
66125 if (!(common_header->flags & LOG_EVENT_SUPPRESS_USE_F) && db && db_len) {
3379
1/2
✓ Branch 0 taken 39013 times.
✗ Branch 1 not taken.
39013 str_buf.append("use ");
3380
1/2
✓ Branch 0 taken 39013 times.
✗ Branch 1 not taken.
39013 append_identifier(this->thd, &str_buf, db, db_len);
3381
1/2
✓ Branch 0 taken 39013 times.
✗ Branch 1 not taken.
39013 str_buf.append("; ");
3382 }
3383 // Add the query to the string
3384
2/4
✓ Branch 0 taken 66125 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66125 times.
✗ Branch 3 not taken.
66125 if (query && q_len) {
3385
1/2
✓ Branch 0 taken 66125 times.
✗ Branch 1 not taken.
66125 str_buf.append(query);
3386
2/2
✓ Branch 0 taken 3671 times.
✓ Branch 1 taken 62454 times.
66125 if (ddl_xid != binary_log::INVALID_XID) {
3387 char xid_buf[64];
3388
1/2
✓ Branch 0 taken 3671 times.
✗ Branch 1 not taken.
3671 str_buf.append(" /* xid=");
3389
1/2
✓ Branch 0 taken 3671 times.
✗ Branch 1 not taken.
3671 longlong10_to_str(ddl_xid, xid_buf, 10);
3390
1/2
✓ Branch 0 taken 3671 times.
✗ Branch 1 not taken.
3671 str_buf.append(xid_buf);
3391
1/2
✓ Branch 0 taken 3671 times.
✗ Branch 1 not taken.
3671 str_buf.append(" */");
3392 }
3393 }
3394 // persist the buffer in protocol
3395
1/2
✓ Branch 0 taken 66125 times.
✗ Branch 1 not taken.
66125 protocol->store_string(str_buf.ptr(), str_buf.length(), &my_charset_bin);
3396 66125 return 0;
3397 66125 }
3398
3399 /**
3400 Utility function for the next method (Query_log_event::write()) .
3401 */
3402 6545939 static void write_str_with_code_and_len(uchar **dst, const char *src,
3403 size_t len, uint code) {
3404 /*
3405 only 1 byte to store the length of catalog, so it should not
3406 surpass 255
3407 */
3408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6545939 times.
6545939 assert(len <= 255);
3409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6545939 times.
6545939 assert(src);
3410 6545939 *((*dst)++) = code;
3411 6545939 *((*dst)++) = (uchar)len;
3412 6545939 memmove(*dst, src, len);
3413 6545939 (*dst) += len;
3414 6545939 }
3415
3416 /**
3417 Query_log_event::write().
3418
3419 @note
3420 In this event we have to modify the header to have the correct
3421 EVENT_LEN_OFFSET as we don't yet know how many status variables we
3422 will print!
3423 */
3424
3425 6696948 bool Query_log_event::write(Basic_ostream *ostream) {
3426 uchar buf[Binary_log_event::QUERY_HEADER_LEN + MAX_SIZE_LOG_EVENT_STATUS];
3427 uchar *start, *start_of_status;
3428 size_t event_length;
3429
3430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6696948 times.
6696948 if (!query) return true; // Something wrong with event
3431
3432 /*
3433 We want to store the thread id:
3434 (- as an information for the user when he reads the binlog)
3435 - if the query uses temporary table: for the slave SQL thread to know to
3436 which master connection the temp table belongs.
3437 Now imagine we (write()) are called by the slave SQL thread (we are
3438 logging a query executed by this thread; the slave runs with
3439 --log-replica-updates). Then this query will be logged with
3440 thread_id=the_thread_id_of_the_SQL_thread. Imagine that 2 temp tables of
3441 the same name were created simultaneously on the master (in the masters
3442 binlog you have
3443 CREATE TEMPORARY TABLE t; (thread 1)
3444 CREATE TEMPORARY TABLE t; (thread 2)
3445 ...)
3446 then in the slave's binlog there will be
3447 CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread)
3448 CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread)
3449 which is bad (same thread id!).
3450
3451 To avoid this, we log the thread's thread id EXCEPT for the SQL
3452 slave thread for which we log the original (master's) thread id.
3453 Now this moves the bug: what happens if the thread id on the
3454 master was 10 and when the slave replicates the query, a
3455 connection number 10 is opened by a normal client on the slave,
3456 and updates a temp table of the same name? We get a problem
3457 again. To avoid this, in the handling of temp tables (sql_base.cc)
3458 we use thread_id AND server_id. TODO when this is merged into
3459 4.1: in 4.1, slave_proxy_id has been renamed to pseudo_thread_id
3460 and is a session variable: that's to make mysqlbinlog work with
3461 temp tables. We probably need to introduce
3462
3463 SET PSEUDO_SERVER_ID
3464 for mysqlbinlog in 4.1. mysqlbinlog would print:
3465 SET PSEUDO_SERVER_ID=
3466 SET PSEUDO_THREAD_ID=
3467 for each query using temp tables.
3468 */
3469 6696948 int4store(buf + Q_THREAD_ID_OFFSET, slave_proxy_id);
3470 6696906 int4store(buf + Q_EXEC_TIME_OFFSET, exec_time);
3471 6697065 buf[Q_DB_LEN_OFFSET] = (char)db_len;
3472 6697065 int2store(buf + Q_ERR_CODE_OFFSET, error_code);
3473
3474 /*
3475 You MUST always write status vars in increasing order of code. This
3476 guarantees that a slightly older slave will be able to parse those he
3477 knows.
3478 */
3479 6697134 start_of_status = start = buf + Binary_log_event::QUERY_HEADER_LEN;
3480
1/2
✓ Branch 0 taken 6697336 times.
✗ Branch 1 not taken.
6697134 if (flags2_inited) {
3481 6697336 *start++ = Q_FLAGS2_CODE;
3482 6697336 int4store(start, flags2);
3483 6697368 start += 4;
3484 }
3485
1/2
✓ Branch 0 taken 6697501 times.
✗ Branch 1 not taken.
6697166 if (sql_mode_inited) {
3486 6697501 *start++ = Q_SQL_MODE_CODE;
3487 6697501 int8store(start, sql_mode);
3488 6697619 start += 8;
3489 }
3490
2/2
✓ Branch 0 taken 6490064 times.
✓ Branch 1 taken 207220 times.
6697284 if (catalog_len) // i.e. this var is inited (false for 4.0 events)
3491 {
3492 6490064 write_str_with_code_and_len(&start, catalog, catalog_len,
3493 Q_CATALOG_NZ_CODE);
3494 /*
3495 In 5.0.x where x<4 masters we used to store the end zero here. This was
3496 a waste of one byte so we don't do it in x>=4 masters. We change code to
3497 Q_CATALOG_NZ_CODE, because re-using the old code would make x<4 slaves
3498 of this x>=4 master segfault (expecting a zero when there is
3499 none). Remaining compatibility problems are: the older slave will not
3500 find the catalog; but it is will not crash, and it's not an issue
3501 that it does not find the catalog as catalogs were not used in these
3502 older MySQL versions (we store it in binlog and read it from relay log
3503 but do nothing useful with it). What is an issue is that the older slave
3504 will stop processing the Q_* blocks (and jumps to the db/query) as soon
3505 as it sees unknown Q_CATALOG_NZ_CODE; so it will not be able to read
3506 Q_AUTO_INCREMENT*, Q_CHARSET and so replication will fail silently in
3507 various ways. Documented that you should not mix alpha/beta versions if
3508 they are not exactly the same version, with example of 5.0.3->5.0.2 and
3509 5.0.4->5.0.3. If replication is from older to new, the new will
3510 recognize Q_CATALOG_CODE and have no problem.
3511 */
3512 }
3513
4/4
✓ Branch 0 taken 6661109 times.
✓ Branch 1 taken 35632 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 6661071 times.
6696741 if (auto_increment_increment != 1 || auto_increment_offset != 1) {
3514 35670 *start++ = Q_AUTO_INCREMENT;
3515 35670 int2store(start, static_cast<uint16>(auto_increment_increment));
3516 36157 int2store(start + 2, static_cast<uint16>(auto_increment_offset));
3517 36157 start += 4;
3518 }
3519
2/2
✓ Branch 0 taken 6697202 times.
✓ Branch 1 taken 26 times.
6697228 if (charset_inited) {
3520 6697202 *start++ = Q_CHARSET_CODE;
3521 6697202 memcpy(start, charset, 6);
3522 6697202 start += 6;
3523 }
3524
2/2
✓ Branch 0 taken 56680 times.
✓ Branch 1 taken 6640548 times.
6697228 if (time_zone_len) {
3525 /* In the TZ sys table, column Name is of length 64 so this should be ok */
3526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56680 times.
56680 assert(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH);
3527 56680 write_str_with_code_and_len(&start, time_zone_str, time_zone_len,
3528 Q_TIME_ZONE_CODE);
3529 }
3530
2/2
✓ Branch 0 taken 2984 times.
✓ Branch 1 taken 6693653 times.
6696637 if (lc_time_names_number) {
3531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2984 times.
2984 assert(lc_time_names_number <= 0xFF);
3532 2984 *start++ = Q_LC_TIME_NAMES_CODE;
3533 2984 int2store(start, lc_time_names_number);
3534 2984 start += 2;
3535 }
3536
2/2
✓ Branch 0 taken 7590 times.
✓ Branch 1 taken 6689047 times.
6696637 if (charset_database_number) {
3537 7590 *start++ = Q_CHARSET_DATABASE_CODE;
3538 7590 int2store(start, charset_database_number);
3539 7590 start += 2;
3540 }
3541
2/2
✓ Branch 0 taken 300021 times.
✓ Branch 1 taken 6396616 times.
6696637 if (table_map_for_update) {
3542 300021 *start++ = Q_TABLE_MAP_FOR_UPDATE_CODE;
3543 300021 int8store(start, table_map_for_update);
3544 300021 start += 8;
3545 }
3546
3547
6/6
✓ Branch 0 taken 6696613 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 30274 times.
✓ Branch 3 taken 6666418 times.
✓ Branch 4 taken 30274 times.
✓ Branch 5 taken 6666442 times.
6696637 if (thd && thd->need_binlog_invoker()) {
3548 30274 LEX_CSTRING invoker_user{nullptr, 0};
3549 30274 LEX_CSTRING invoker_host{nullptr, 0};
3550 30274 memset(&invoker_user, 0, sizeof(invoker_user));
3551 30274 memset(&invoker_host, 0, sizeof(invoker_host));
3552
3553
6/6
✓ Branch 0 taken 2866 times.
✓ Branch 1 taken 27408 times.
✓ Branch 2 taken 2857 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 2857 times.
✓ Branch 5 taken 27417 times.
30274 if (thd->slave_thread && thd->has_invoker()) {
3554 /* user will be null, if master is older than this patch */
3555 2857 invoker_user = thd->get_invoker_user();
3556 2857 invoker_host = thd->get_invoker_host();
3557 } else {
3558 27417 Security_context *ctx = thd->security_context();
3559
1/2
✓ Branch 0 taken 27417 times.
✗ Branch 1 not taken.
27417 LEX_CSTRING priv_user = ctx->priv_user();
3560
1/2
✓ Branch 0 taken 27417 times.
✗ Branch 1 not taken.
27417 LEX_CSTRING priv_host = ctx->priv_host();
3561
3562 27417 invoker_user.length = priv_user.length;
3563 27417 invoker_user.str = priv_user.str;
3564
2/2
✓ Branch 0 taken 27411 times.
✓ Branch 1 taken 6 times.
27417 if (priv_host.str[0] != '\0') {
3565 27411 invoker_host.str = priv_host.str;
3566 27411 invoker_host.length = priv_host.length;
3567 }
3568 }
3569
3570 30274 *start++ = Q_INVOKER;
3571
3572
3/4
✓ Branch 0 taken 30274 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 30273 times.
30274 DBUG_EXECUTE_IF("wl12571_long_invoker_host", {
3573 invoker_host.str =
3574 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
3575 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
3576 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
3577 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
3578 invoker_host.length = strlen(invoker_host.str);
3579 });
3580
3581 /*
3582 Store user length and user. The max length of use is 16, so 1 byte is
3583 enough to store the user's length.
3584 */
3585 30274 *start++ = (uchar)invoker_user.length;
3586 30274 memcpy(start, invoker_user.str, invoker_user.length);
3587 30274 start += invoker_user.length;
3588
3589 /*
3590 Store host length and host. The max length of host is 255, so 1 byte
3591 is enough to store the host's length.
3592 */
3593 30274 *start++ = (uchar)invoker_host.length;
3594
2/2
✓ Branch 0 taken 30267 times.
✓ Branch 1 taken 7 times.
30274 if (invoker_host.length > 0)
3595 30267 memcpy(start, invoker_host.str, invoker_host.length);
3596 30274 start += invoker_host.length;
3597 }
3598
3599
6/6
✓ Branch 0 taken 6696655 times.
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 882658 times.
✓ Branch 3 taken 5814306 times.
✓ Branch 4 taken 882718 times.
✓ Branch 5 taken 5814307 times.
6696716 if (thd && thd->get_binlog_accessed_db_names() != nullptr) {
3600 uchar dbs;
3601 882718 *start++ = Q_UPDATED_DB_NAMES;
3602
3603 static_assert(MAX_DBS_IN_EVENT_MTS <= OVER_MAX_DBS_IN_EVENT_MTS, "");
3604
3605 /*
3606 In case of the number of db:s exceeds MAX_DBS_IN_EVENT_MTS
3607 no db:s is written and event will require the sequential applying on
3608 slave.
3609 */
3610 84 dbs =
3611
2/2
✓ Branch 0 taken 882652 times.
✓ Branch 1 taken 84 times.
882718 (thd->get_binlog_accessed_db_names()->elements <= MAX_DBS_IN_EVENT_MTS)
3612 882652 ? thd->get_binlog_accessed_db_names()->elements
3613 : OVER_MAX_DBS_IN_EVENT_MTS;
3614
3615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 882785 times.
882785 assert(dbs != 0);
3616
3617
2/2
✓ Branch 0 taken 882704 times.
✓ Branch 1 taken 81 times.
882785 if (dbs <= MAX_DBS_IN_EVENT_MTS) {
3618
1/2
✓ Branch 0 taken 882448 times.
✗ Branch 1 not taken.
882704 List_iterator_fast<char> it(*thd->get_binlog_accessed_db_names());
3619 882448 char *db_name = it++;
3620 /*
3621 the single "" db in the accessed db list corresponds to the same as
3622 exceeds MAX_DBS_IN_EVENT_MTS case, so dbs is set to the over-max.
3623 */
3624
4/4
✓ Branch 0 taken 876563 times.
✓ Branch 1 taken 6063 times.
✓ Branch 2 taken 937 times.
✓ Branch 3 taken 875626 times.
882626 if (dbs == 1 && !strcmp(db_name, "")) dbs = OVER_MAX_DBS_IN_EVENT_MTS;
3625 882626 *start++ = dbs;
3626
2/2
✓ Branch 0 taken 881741 times.
✓ Branch 1 taken 885 times.
882626 if (dbs != OVER_MAX_DBS_IN_EVENT_MTS) do {
3627 899414 strcpy((char *)start, db_name);
3628 899414 start += strlen(db_name) + 1;
3629
2/2
✓ Branch 0 taken 17673 times.
✓ Branch 1 taken 881783 times.
899414 } while ((db_name = it++));
3630 } else {
3631 81 *start++ = dbs;
3632 }
3633 }
3634
3635
4/4
✓ Branch 0 taken 6696820 times.
✓ Branch 1 taken 236 times.
✓ Branch 2 taken 8381 times.
✓ Branch 3 taken 6688439 times.
6697056 if (thd && thd->query_start_usec_used) {
3636 8381 *start++ = Q_MICROSECONDS;
3637
1/2
✓ Branch 0 taken 8381 times.
✗ Branch 1 not taken.
8381 get_time();
3638 8381 int3store(start, common_header->when.tv_usec);
3639 8381 start += 3;
3640 }
3641
3642
3/4
✓ Branch 0 taken 6697060 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20405 times.
✓ Branch 3 taken 6676655 times.
6697056 if (thd && thd->binlog_need_explicit_defaults_ts == true) {
3643 20405 *start++ = Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP;
3644 20405 *start++ = thd->variables.explicit_defaults_for_timestamp;
3645 }
3646
3647
2/2
✓ Branch 0 taken 265694 times.
✓ Branch 1 taken 6431362 times.
6697056 if (ddl_xid != binary_log::INVALID_XID) {
3648 265694 *start++ = Q_DDL_LOGGED_WITH_XID;
3649 265694 int8store(start, ddl_xid);
3650 265694 start += 8;
3651 }
3652
3653
2/2
✓ Branch 0 taken 6696958 times.
✓ Branch 1 taken 98 times.
6697056 if (default_collation_for_utf8mb4_number) {
3654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6696958 times.
6696958 assert(default_collation_for_utf8mb4_number <= 0xFF);
3655 6696958 *start++ = Q_DEFAULT_COLLATION_FOR_UTF8MB4;
3656 6696958 int2store(start, default_collation_for_utf8mb4_number);
3657 6697395 start += 2;
3658 }
3659
3660
4/4
✓ Branch 0 taken 6697473 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 147813 times.
✓ Branch 3 taken 6549660 times.
6697493 if (thd && need_sql_require_primary_key) {
3661 147813 *start++ = Q_SQL_REQUIRE_PRIMARY_KEY;
3662 147813 *start++ = thd->variables.sql_require_primary_key;
3663 }
3664
3665
4/4
✓ Branch 0 taken 6697484 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 4687 times.
✓ Branch 3 taken 6692797 times.
6697493 if (thd && needs_default_table_encryption) {
3666 4687 *start++ = Q_DEFAULT_TABLE_ENCRYPTION;
3667 4687 *start++ = thd->variables.default_table_encryption;
3668 }
3669
3670 /*
3671 NOTE: When adding new status vars, please don't forget to update
3672 the MAX_SIZE_LOG_EVENT_STATUS in log_event.h
3673
3674 Here there could be code like
3675 if (command-line-option-which-says-"log_this_variable" && inited)
3676 {
3677 *start++= Q_THIS_VARIABLE_CODE;
3678 int4store(start, this_variable);
3679 start+= 4;
3680 }
3681 */
3682
3683 /* Store length of status variables */
3684 6697493 status_vars_len = (uint)(start - start_of_status);
3685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6697493 times.
6697493 assert(status_vars_len <= MAX_SIZE_LOG_EVENT_STATUS);
3686 6697493 int2store(buf + Q_STATUS_VARS_LEN_OFFSET, status_vars_len);
3687
3688 /*
3689 Calculate length of whole event
3690 The "1" below is the \0 in the db's length
3691 */
3692
1/2
✓ Branch 0 taken 6696417 times.
✗ Branch 1 not taken.
6697382 event_length = (uint)(start - buf) + get_post_header_size_for_derived() +
3693 6696417 db_len + 1 + q_len;
3694
3695
1/2
✓ Branch 0 taken 6697529 times.
✗ Branch 1 not taken.
6696417 return (write_header(ostream, event_length) ||
3696
3/4
✓ Branch 0 taken 6697585 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6697565 times.
✓ Branch 3 taken 20 times.
6697551 wrapper_my_b_safe_write(ostream, (uchar *)buf,
3697 6697369 Binary_log_event::QUERY_HEADER_LEN) ||
3698
2/4
✓ Branch 0 taken 6697369 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6697414 times.
✗ Branch 3 not taken.
6697565 write_post_header_for_derived(ostream) ||
3699
1/2
✓ Branch 0 taken 6697550 times.
✗ Branch 1 not taken.
6697544 wrapper_my_b_safe_write(ostream, start_of_status,
3700
1/2
✓ Branch 0 taken 6697544 times.
✗ Branch 1 not taken.
6697414 (uint)(start - start_of_status)) ||
3701
2/4
✓ Branch 0 taken 6697637 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6697651 times.
✗ Branch 3 not taken.
6697392 wrapper_my_b_safe_write(ostream,
3702 6642009 db ? pointer_cast<const uchar *>(db)
3703 55541 : pointer_cast<const uchar *>(""),
3704
2/2
✓ Branch 0 taken 6642009 times.
✓ Branch 1 taken 55541 times.
6697550 db_len + 1) ||
3705
3/4
✓ Branch 0 taken 6697724 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6697602 times.
✓ Branch 3 taken 122 times.
6697651 wrapper_my_b_safe_write(ostream, pointer_cast<const uchar *>(query),
3706 q_len) ||
3707
1/2
✓ Branch 0 taken 6697551 times.
✗ Branch 1 not taken.
6697602 write_footer(ostream))
3708
2/4
✓ Branch 0 taken 6697551 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6697553 times.
13395157 ? true
3709 6697606 : false;
3710 }
3711
3712 /**
3713 The simplest constructor that could possibly work. This is used for
3714 creating static objects that have a special meaning and are invisible
3715 to the log.
3716 */
3717 Query_log_event::Query_log_event()
3718 : binary_log::Query_event(),
3719 Log_event(header(), footer()),
3720 data_buf(nullptr) {}
3721
3722 /**
3723 Returns true when the lex context determines an atomic DDL.
3724 The result is optimistic as there can be more properties to check out.
3725
3726 CREATE TABLE ... START TRANSACTION is not treated as atomic here, because
3727 the table is not really committed at the end of CREATE TABLE processing.
3728 It gets committed by a explicit call to COMMIT after INSERTing rows into
3729 the table.
3730
3731 @param lex pointer to LEX object of being executed statement
3732 */
3733 575758 inline bool is_sql_command_atomic_ddl(const LEX *lex) {
3734 755186 return ((sql_command_flags[lex->sql_command] & CF_POTENTIAL_ATOMIC_DDL) &&
3735
1/2
✓ Branch 0 taken 179428 times.
✗ Branch 1 not taken.
179428 lex->sql_command != SQLCOM_OPTIMIZE &&
3736
1/2
✓ Branch 0 taken 179428 times.
✗ Branch 1 not taken.
179428 lex->sql_command != SQLCOM_REPAIR &&
3737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 179428 times.
179428 lex->sql_command != SQLCOM_ANALYZE) ||
3738
2/2
✓ Branch 0 taken 104336 times.
✓ Branch 1 taken 291994 times.
396330 (lex->sql_command == SQLCOM_CREATE_TABLE &&
3739
2/2
✓ Branch 0 taken 96414 times.
✓ Branch 1 taken 7922 times.
104336 !(lex->create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
3740
4/4
✓ Branch 0 taken 179428 times.
✓ Branch 1 taken 396330 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 96351 times.
1151579 !lex->create_info->m_transactional_ddl) ||
3741
4/4
✓ Branch 0 taken 71652 times.
✓ Branch 1 taken 228327 times.
✓ Branch 2 taken 70856 times.
✓ Branch 3 taken 796 times.
875737 (lex->sql_command == SQLCOM_DROP_TABLE && !lex->drop_temporary);
3742 }
3743
3744 /**
3745 Returns whether or not the statement held by the `LEX` object parameter
3746 requires `Q_SQL_REQUIRE_PRIMARY_KEY` to be logged together with the statement.
3747 */
3748 815794 static bool is_sql_require_primary_key_needed(const LEX *lex) {
3749 815794 enum enum_sql_command cmd = lex->sql_command;
3750
2/2
✓ Branch 0 taken 166517 times.
✓ Branch 1 taken 649277 times.
815794 switch (cmd) {
3751 166517 case SQLCOM_CREATE_TABLE:
3752 case SQLCOM_ALTER_TABLE:
3753 166517 return true;
3754 649277 default:
3755 649277 break;
3756 }
3757 649277 return false;
3758 }
3759
3760 /**
3761 Returns whether or not the statement held by the `LEX` object parameter
3762 requires `Q_DEFAULT_TABLE_ENCRYPTION` to be logged together with the
3763 statement.
3764 */
3765 815809 static bool is_default_table_encryption_needed(const LEX *lex) {
3766 815809 enum enum_sql_command cmd = lex->sql_command;
3767
3/3
✓ Branch 0 taken 5308 times.
✓ Branch 1 taken 7116 times.
✓ Branch 2 taken 803385 times.
815809 switch (cmd) {
3768 5308 case SQLCOM_CREATE_DB:
3769 // If it is CREATE DATABASE without an ENCRYPTION clause
3770 5308 return !(lex->create_info->used_fields &
3771 5308 HA_CREATE_USED_DEFAULT_ENCRYPTION);
3772 7116 case SQLCOM_ALTER_TABLESPACE: {
3773 /*
3774 If it is CREATE TABLESPACE without an ENCRYPTION clause. Note
3775 that CREATE TABLESPACE uses SQLCOM_ALTER_TABLESPACE, so to
3776 know if it is really a CREATE TABLESPACE we check that the
3777 dynamic_cast to Sql_cmd_create_tablespace works.
3778 */
3779 7116 const Sql_cmd_tablespace *sct =
3780
1/2
✓ Branch 0 taken 7116 times.
✗ Branch 1 not taken.
7116 dynamic_cast<const Sql_cmd_create_tablespace *>(lex->m_sql_cmd);
3781
2/2
✓ Branch 0 taken 873 times.
✓ Branch 1 taken 6243 times.
7989 return ((sct != nullptr) &&
3782
2/2
✓ Branch 0 taken 364 times.
✓ Branch 1 taken 509 times.
7989 (sct->get_options().encryption.str == nullptr));
3783 }
3784 803385 default:
3785 803385 break;
3786 }
3787 803385 return false;
3788 }
3789
3790 683567 bool is_atomic_ddl(THD *thd, bool using_trans_arg) {
3791 683567 LEX *lex = thd->lex;
3792
3793 #ifndef NDEBUG
3794 683567 enum enum_sql_command cmd = lex->sql_command;
3795
3/3
✓ Branch 0 taken 56445 times.
✓ Branch 1 taken 25300 times.
✓ Branch 2 taken 601822 times.
683567 switch (cmd) {
3796 56445 case SQLCOM_CREATE_USER:
3797 case SQLCOM_RENAME_USER:
3798 case SQLCOM_DROP_USER:
3799 case SQLCOM_ALTER_USER:
3800 case SQLCOM_ALTER_USER_DEFAULT_ROLE:
3801 case SQLCOM_GRANT:
3802 case SQLCOM_GRANT_ROLE:
3803 case SQLCOM_REVOKE:
3804 case SQLCOM_REVOKE_ALL:
3805 case SQLCOM_REVOKE_ROLE:
3806 case SQLCOM_DROP_ROLE:
3807 case SQLCOM_CREATE_ROLE:
3808 case SQLCOM_SET_PASSWORD:
3809 case SQLCOM_DROP_TRIGGER:
3810 case SQLCOM_ALTER_FUNCTION:
3811 case SQLCOM_DROP_FUNCTION:
3812 case SQLCOM_DROP_PROCEDURE:
3813 case SQLCOM_ALTER_PROCEDURE:
3814 case SQLCOM_ALTER_EVENT:
3815 case SQLCOM_DROP_EVENT:
3816 case SQLCOM_CREATE_VIEW:
3817 case SQLCOM_DROP_VIEW:
3818
3819
5/6
✓ Branch 0 taken 4613 times.
✓ Branch 1 taken 51832 times.
✓ Branch 2 taken 4376 times.
✓ Branch 3 taken 237 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4376 times.
56445 assert(using_trans_arg || thd->slave_thread || lex->drop_if_exists);
3820
3821 56445 break;
3822
3823 25300 case SQLCOM_CREATE_EVENT:
3824 case SQLCOM_CREATE_PROCEDURE:
3825 case SQLCOM_CREATE_SPFUNCTION:
3826 case SQLCOM_CREATE_FUNCTION:
3827 case SQLCOM_CREATE_TRIGGER:
3828 /*
3829 trx cache is *not* used if object already exists and IF NOT EXISTS
3830 clause is used in the statement or if call is from the slave applier.
3831 */
3832
4/6
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 25278 times.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 22 times.
25300 assert(using_trans_arg || thd->slave_thread ||
3833 (lex->create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS));
3834 25300 break;
3835
3836 601822 default:
3837 601822 break;
3838 }
3839 #endif
3840
3841
4/4
✓ Branch 0 taken 575763 times.
✓ Branch 1 taken 107804 times.
✓ Branch 2 taken 346635 times.
✓ Branch 3 taken 229131 times.
683567 return using_trans_arg && is_sql_command_atomic_ddl(lex);
3842 }
3843
3844 /**
3845 Creates a Query Log Event.
3846
3847 @param thd_arg Thread handle
3848 @param query_arg Array of char representing the query
3849 @param query_length Size of the 'query_arg' array
3850 @param using_trans Indicates that there are transactional changes.
3851 @param immediate After being written to the binary log, the event
3852 must be flushed immediately. This indirectly implies
3853 the stmt-cache.
3854 @param suppress_use Suppress the generation of 'USE' statements
3855 @param errcode The error code of the query
3856 @param ignore_cmd_internals Ignore user's statement, i.e. lex
3857 information, while deciding which cache must be used.
3858 */
3859 13645584 Query_log_event::Query_log_event(THD *thd_arg, const char *query_arg,
3860 size_t query_length, bool using_trans,
3861 bool immediate, bool suppress_use, int errcode,
3862 13637340 bool ignore_cmd_internals)
3863
3864 : binary_log::Query_event(
3865 13638234 query_arg, thd_arg->catalog().str, thd_arg->db().str, query_length,
3866 13637340 thd_arg->thread_id(), thd_arg->variables.sql_mode,
3867 thd_arg->variables.auto_increment_increment,
3868 thd_arg->variables.auto_increment_offset,
3869 13637340 thd_arg->variables.lc_time_names->number,
3870 13637340 (ulonglong)thd_arg->table_map_for_update, errcode),
3871 Log_event(
3872 thd_arg,
3873
4/4
✓ Branch 0 taken 177315 times.
✓ Branch 1 taken 6646424 times.
✓ Branch 2 taken 6036799 times.
✓ Branch 3 taken 786940 times.
13647478 (thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F : 0) |
3874 (suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0),
3875 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
3876 : Log_event::EVENT_STMT_CACHE,
3877 Log_event::EVENT_NORMAL_LOGGING, header(), footer()),
3878
5/6
✓ Branch 0 taken 3601 times.
✓ Branch 1 taken 521 times.
✓ Branch 2 taken 5878078 times.
✓ Branch 3 taken 941539 times.
✓ Branch 4 taken 6819415 times.
✗ Branch 5 not taken.
40931106 data_buf(nullptr) {
3879 /* save the original thread id; we already know the server id */
3880 13647074 slave_proxy_id = thd_arg->variables.pseudo_thread_id;
3881 13647074 common_header->set_is_valid(query != nullptr);
3882
3883 /*
3884 exec_time calculation has changed to use the same method that is used
3885 to fill out "thd_arg->start_time"
3886 */
3887
3888 struct timeval end_time;
3889 13647312 ulonglong micro_end_time = my_micro_time();
3890 13647042 my_micro_time_to_timeval(micro_end_time, &end_time);
3891
3892 13646614 exec_time = end_time.tv_sec - thd_arg->query_start_in_secs();
3893
3894 /**
3895 @todo this means that if we have no catalog, then it is replicated
3896 as an existing catalog of length zero. is that safe? /sven
3897 */
3898
2/2
✓ Branch 0 taken 6615599 times.
✓ Branch 1 taken 207514 times.
13646226 catalog_len = (catalog) ? strlen(catalog) : 0;
3899 /* status_vars_len is set just before writing the event */
3900
2/2
✓ Branch 0 taken 6765628 times.
✓ Branch 1 taken 57485 times.
13646226 db_len = (db) ? strlen(db) : 0;
3901
2/2
✓ Branch 0 taken 7654 times.
✓ Branch 1 taken 6815459 times.
13646226 if (thd_arg->variables.collation_database != thd_arg->db_charset)
3902 15308 charset_database_number = thd_arg->variables.collation_database->number;
3903
3904 13646226 default_collation_for_utf8mb4_number =
3905 13646226 thd_arg->variables.default_collation_for_utf8mb4->number;
3906
3907 /*
3908 We only replicate over the bits of flags2 that we need: the rest
3909 are masked out by "& OPTIONS_WRITTEN_TO_BINLOG".
3910
3911 We also force AUTOCOMMIT=1. Rationale (cf. BUG#29288): After
3912 fixing BUG#26395, we always write BEGIN and COMMIT around all
3913 transactions (even single statements in autocommit mode). This is
3914 so that replication from non-transactional to transactional table
3915 and error recovery from XA to non-XA table should work as
3916 expected. The BEGIN/COMMIT are added in log.cc. However, there is
3917 one exception: MyISAM bypasses log.cc and writes directly to the
3918 binlog. So if autocommit is off, master has MyISAM, and slave has
3919 a transactional engine, then the slave will just see one long
3920 never-ending transaction. The only way to bypass explicit
3921 BEGIN/COMMIT in the binlog is by using a non-transactional table.
3922 So setting AUTOCOMMIT=1 will make this work as expected.
3923
3924 Note: explicitly replicate AUTOCOMMIT=1 from master. We do not
3925 assume AUTOCOMMIT=1 on slave; the slave still reads the state of
3926 the autocommit flag as written by the master to the binlog. This
3927 behavior may change after WL#4162 has been implemented.
3928 */
3929 13646226 flags2 = (uint32)(thd_arg->variables.option_bits &
3930 (OPTIONS_WRITTEN_TO_BIN_LOG & ~OPTION_NOT_AUTOCOMMIT));
3931
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6823113 times.
13646226 assert(thd_arg->variables.character_set_client->number < 256 * 256);
3932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6823113 times.
13646226 assert(thd_arg->variables.collation_connection->number < 256 * 256);
3933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6823113 times.
13646226 assert(thd_arg->variables.collation_server->number < 256 * 256);
3934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6823113 times.
13646226 assert(thd_arg->variables.character_set_client->mbminlen == 1);
3935 13646226 int2store(charset, thd_arg->variables.character_set_client->number);
3936 13646168 int2store(charset + 2, thd_arg->variables.collation_connection->number);
3937 13647594 int2store(charset + 4, thd_arg->variables.collation_server->number);
3938
2/2
✓ Branch 0 taken 57054 times.
✓ Branch 1 taken 6766767 times.
13647642 if (thd_arg->time_zone_used) {
3939 /*
3940 Note that our event becomes dependent on the Time_zone object
3941 representing the time zone. Fortunately such objects are never deleted
3942 or changed during mysqld's lifetime.
3943 */
3944
1/2
✓ Branch 0 taken 57054 times.
✗ Branch 1 not taken.
114108 time_zone_len = thd_arg->variables.time_zone->get_name()->length();
3945
1/2
✓ Branch 0 taken 57054 times.
✗ Branch 1 not taken.
114108 time_zone_str = thd_arg->variables.time_zone->get_name()->ptr();
3946 } else
3947 13533534 time_zone_len = 0;
3948
3949 /*
3950 In what follows, we define in which cache, trx-cache or stmt-cache,
3951 this Query Log Event will be written to.
3952
3953 If ignore_cmd_internals is defined, we rely on the is_trans flag to
3954 choose the cache and this is done in the base class Log_event. False
3955 means that the stmt-cache will be used and upon statement commit/rollback
3956 the cache will be flushed to disk. True means that the trx-cache will
3957 be used and upon transaction commit/rollback the cache will be flushed
3958 to disk.
3959
3960 If set immediate cache is defined, for convenience, we automatically
3961 use the stmt-cache. This mean that the statement will be written
3962 to the stmt-cache and immediately flushed to disk without waiting
3963 for a commit/rollback notification.
3964
3965 For example, the cluster/ndb captures a request to execute a DDL
3966 statement and synchronously propagate it to all available MySQL
3967 servers. Unfortunately, the current protocol assumes that the
3968 generated events are immediately written to diks and does not check
3969 for commit/rollback.
3970
3971 Upon dropping a connection, DDLs (i.e. DROP TEMPORARY TABLE) are
3972 generated and in this case the statements have the immediate flag
3973 set because there is no commit/rollback.
3974
3975 If the immediate flag is not set, the decision on the cache is based
3976 on the current statement and the flag is_trans, which indicates if
3977 a transactional engine was updated.
3978
3979 Statements are classified as row producers (i.e. can_generate_row_events())
3980 or non-row producers. Non-row producers, DDL in general, are treated
3981 as the immediate flag was set and for convenience are written to the
3982 stmt-cache and immediately flushed to disk.
3983
3984 Row producers are handled in general according to the is_trans flag.
3985 False means that the stmt-cache will be used and upon statement
3986 commit/rollback the cache will be flushed to disk. True means that the
3987 trx-cache will be used and upon transaction commit/rollback the cache
3988 will be flushed to disk.
3989
3990 Unfortunately, there are exceptions to this non-row and row producer
3991 rules:
3992
3993 . The SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT does not
3994 have the flag is_trans set because there is no updated engine but
3995 must be written to the trx-cache.
3996
3997 . SET If auto-commit is on, it must not go through a cache.
3998
3999 . CREATE TABLE is classfied as non-row producer but CREATE TEMPORARY
4000 must be handled as row producer.
4001
4002 . DROP TABLE is classfied as non-row producer but DROP TEMPORARY
4003 must be handled as row producer.
4004
4005 Finally, some statements that does not have the flag is_trans set may
4006 be written to the trx-cache based on the following criteria:
4007
4008 . updated both a transactional and a non-transactional engine (i.e.
4009 stmt_has_updated_trans_table()).
4010
4011 . accessed both a transactional and a non-transactional engine and
4012 is classified as unsafe (i.e. is_mixed_stmt_unsafe()).
4013
4014 . is executed within a transaction and previously a transactional
4015 engine was updated and the flag binlog_direct_non_trans_update
4016 is set.
4017 */
4018
2/2
✓ Branch 0 taken 6008018 times.
✓ Branch 1 taken 815803 times.
13647642 if (ignore_cmd_internals) return;
4019
4020 /*
4021 true defines that the trx-cache must be used.
4022 */
4023 1631606 bool cmd_can_generate_row_events = false;
4024 /*
4025 true defines that the trx-cache must be used.
4026 */
4027 1631606 bool cmd_must_go_to_trx_cache = false;
4028
4029 1631606 LEX *lex = thd->lex;
4030
2/2
✓ Branch 0 taken 812367 times.
✓ Branch 1 taken 3436 times.
1631606 if (!immediate) {
4031
5/5
✓ Branch 0 taken 98372 times.
✓ Branch 1 taken 131888 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 15676 times.
✓ Branch 4 taken 566357 times.
1624734 switch (lex->sql_command) {
4032 196744 case SQLCOM_DROP_TABLE:
4033 196744 cmd_can_generate_row_events =
4034
4/4
✓ Branch 0 taken 1577 times.
✓ Branch 1 taken 96795 times.
✓ Branch 2 taken 318 times.
✓ Branch 3 taken 1259 times.
196744 lex->drop_temporary && thd->in_multi_stmt_transaction_mode();
4035 196744 break;
4036 263776 case SQLCOM_CREATE_TABLE:
4037
5/6
✓ Branch 0 taken 131888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6648 times.
✓ Branch 3 taken 125240 times.
✓ Branch 4 taken 5629 times.
✓ Branch 5 taken 1019 times.
277072 cmd_must_go_to_trx_cache = !lex->query_block->field_list_is_empty() &&
4038 13296 thd->is_current_stmt_binlog_format_row();
4039 263776 cmd_can_generate_row_events =
4040
2/2
✓ Branch 0 taken 9761 times.
✓ Branch 1 taken 626 times.
20774 ((lex->create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
4041
4/4
✓ Branch 0 taken 10387 times.
✓ Branch 1 taken 121501 times.
✓ Branch 2 taken 5629 times.
✓ Branch 3 taken 125633 times.
284550 thd->in_multi_stmt_transaction_mode()) ||
4042 cmd_must_go_to_trx_cache;
4043 263776 break;
4044 148 case SQLCOM_SET_OPTION:
4045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
148 if (lex->autocommit)
4046 cmd_can_generate_row_events = cmd_must_go_to_trx_cache = false;
4047 else
4048 148 cmd_can_generate_row_events = true;
4049 148 break;
4050 31352 case SQLCOM_RELEASE_SAVEPOINT:
4051 case SQLCOM_ROLLBACK_TO_SAVEPOINT:
4052 case SQLCOM_SAVEPOINT:
4053 case SQLCOM_XA_PREPARE:
4054 31352 cmd_can_generate_row_events = cmd_must_go_to_trx_cache = true;
4055 31352 break;
4056 1132714 default:
4057 cmd_can_generate_row_events =
4058
1/2
✓ Branch 0 taken 566271 times.
✗ Branch 1 not taken.
1132714 sqlcom_can_generate_row_events(thd->lex->sql_command);
4059 1132542 break;
4060 }
4061 } else {
4062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3436 times.
6872 assert(!using_trans); // immediate is incompatible with using_trans
4063 }
4064
4065 /*
4066 Drop the flag as sort of reset right before the query being logged
4067 gets classified as possibly not atomic DDL.
4068 */
4069
2/2
✓ Branch 0 taken 185455 times.
✓ Branch 1 taken 630262 times.
1631434 if (thd->rli_slave) thd->rli_slave->ddl_not_atomic = false;
4070
4071
2/2
✓ Branch 0 taken 378957 times.
✓ Branch 1 taken 436760 times.
1631434 if (cmd_can_generate_row_events) {
4072
4/4
✓ Branch 0 taken 357674 times.
✓ Branch 1 taken 21283 times.
✓ Branch 2 taken 279461 times.
✓ Branch 3 taken 78213 times.
757914 cmd_must_go_to_trx_cache = cmd_must_go_to_trx_cache || using_trans;
4073 1070542 if (cmd_must_go_to_trx_cache ||
4074
3/4
✓ Branch 0 taken 78176 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77499 times.
✓ Branch 3 taken 677 times.
156118 stmt_has_updated_trans_table(
4075
3/6
✓ Branch 0 taken 78059 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 302004 times.
✓ Branch 3 taken 77032 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
914648 thd->get_transaction()->ha_trx_info(Transaction_ctx::STMT)) ||
4076
3/4
✓ Branch 0 taken 77682 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77542 times.
✓ Branch 3 taken 140 times.
155002 thd->lex->is_mixed_stmt_unsafe(
4077 155016 thd->in_multi_stmt_transaction_mode(),
4078 155016 thd->variables.binlog_direct_non_trans_update,
4079
5/6
✓ Branch 0 taken 78239 times.
✓ Branch 1 taken 300718 times.
✓ Branch 2 taken 77508 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 78300 times.
✓ Branch 5 taken 300785 times.
1069646 trans_has_updated_trans_table(thd), thd->tx_isolation) ||
4080
2/2
✓ Branch 0 taken 74785 times.
✓ Branch 1 taken 2757 times.
155084 (!thd->variables.binlog_direct_non_trans_update &&
4081
3/4
✓ Branch 0 taken 74793 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 469 times.
✓ Branch 3 taken 74324 times.
149570 trans_has_updated_trans_table(thd))) {
4082 604008 event_logging_type = Log_event::EVENT_NORMAL_LOGGING;
4083 604008 event_cache_type = Log_event::EVENT_TRANSACTIONAL_CACHE;
4084 } else {
4085 154064 event_logging_type = Log_event::EVENT_NORMAL_LOGGING;
4086 154064 event_cache_type = Log_event::EVENT_STMT_CACHE;
4087 }
4088
3/4
✓ Branch 0 taken 436983 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 318077 times.
✓ Branch 3 taken 118906 times.
873520 } else if (is_atomic_ddl(thd, using_trans)) {
4089
2/4
✓ Branch 0 taken 318077 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 318077 times.
636154 assert(stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END));
4090 /*
4091 Event creation is normally followed by its logging.
4092 Todo: add exceptions if any.
4093 */
4094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 318077 times.
636154 assert(!thd->is_operating_substatement_implicitly);
4095
4096 636154 Transaction_ctx *trn_ctx = thd->get_transaction();
4097
4098 /* Transaction needs to be active for xid to be assigned, */
4099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 318077 times.
636154 assert(trn_ctx->is_active(Transaction_ctx::SESSION));
4100 /* and the transaction's xid has been already computed. */
4101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 318077 times.
636154 assert(!trn_ctx->xid_state()->get_xid()->is_null());
4102
4103
1/2
✓ Branch 0 taken 318077 times.
✗ Branch 1 not taken.
636154 my_xid xid = trn_ctx->xid_state()->get_xid()->get_my_xid();
4104
4105 /*
4106 xid uniqueness: the last time used not equal to the current one
4107 */
4108
4/6
✓ Branch 0 taken 287794 times.
✓ Branch 1 taken 30283 times.
✓ Branch 2 taken 287794 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 287794 times.
636154 assert(thd->debug_binlog_xid_last.is_null() ||
4109 thd->debug_binlog_xid_last.get_my_xid() != xid);
4110
4111 636154 ddl_xid = xid;
4112 #ifndef NDEBUG
4113 636154 thd->debug_binlog_xid_last = *trn_ctx->xid_state()->get_xid();
4114 #endif
4115 636154 event_logging_type = Log_event::EVENT_NORMAL_LOGGING;
4116 636154 event_cache_type = Log_event::EVENT_TRANSACTIONAL_CACHE;
4117
2/2
✓ Branch 0 taken 38725 times.
✓ Branch 1 taken 80181 times.
237812 } else if (thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
4118
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 38662 times.
77450 thd->lex->create_info->m_transactional_ddl) {
4119 /*
4120 When executing CREATE-TABLE-SELECT using engine that support atomic
4121 DDL's, we cache the CREATE-TABLE event using normal logging. This
4122 enables using single transaction for execution of both CREATE-TABLE
4123 and INSERT's when applying the binlog events at slave.
4124 */
4125 126 event_logging_type = Log_event::EVENT_NORMAL_LOGGING;
4126 126 event_cache_type = Log_event::EVENT_TRANSACTIONAL_CACHE;
4127
4128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
126 assert(ddl_xid == binary_log::INVALID_XID);
4129
4130
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 16 times.
126 if (thd->rli_slave) thd->rli_slave->ddl_not_atomic = true;
4131 } else {
4132 /*
4133 Note SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK fall into this block.
4134 Even though CREATE-TABLE sub-statement of CREATE-TABLE-SELECT in
4135 RBR makes a turn here it is logged atomically with the SELECT
4136 Rows-log event part that determines the xid of the entire group.
4137 */
4138 237686 event_logging_type = Log_event::EVENT_IMMEDIATE_LOGGING;
4139 237686 event_cache_type = Log_event::EVENT_STMT_CACHE;
4140
4141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118843 times.
237686 assert(ddl_xid == binary_log::INVALID_XID);
4142
4143
2/2
✓ Branch 0 taken 13086 times.
✓ Branch 1 taken 105757 times.
237686 if (thd->rli_slave) thd->rli_slave->ddl_not_atomic = true;
4144 }
4145
4146 1632038 need_sql_require_primary_key = is_sql_require_primary_key_needed(lex);
4147
4148 1631676 needs_default_table_encryption = is_default_table_encryption_needed(lex);
4149
4150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 815853 times.
1631706 assert(event_cache_type != Log_event::EVENT_INVALID_CACHE);
4151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 815853 times.
1631706 assert(event_logging_type != Log_event::EVENT_INVALID_LOGGING);
4152
5/8
✓ Branch 0 taken 815978 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 816025 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 90 times.
✓ Branch 5 taken 815935 times.
✓ Branch 6 taken 70 times.
✗ Branch 7 not taken.
1631706 DBUG_PRINT("info", ("Query_log_event has flags2: %lu sql_mode: %llu",
4153 (ulong)flags2, (ulonglong)sql_mode));
4154 }
4155 #endif /* MYSQL_SERVER */
4156
4157 /**
4158 This is used by the SQL slave thread to prepare the event before execution.
4159 */
4160 7518696 Query_log_event::Query_log_event(
4161 const char *buf, const Format_description_event *description_event,
4162 7518332 Log_event_type event_type)
4163 : binary_log::Query_event(buf, description_event, event_type),
4164 Log_event(header(), footer()),
4165
1/2
✓ Branch 0 taken 3697330 times.
✗ Branch 1 not taken.
7518696 has_ddl_committed(false) {
4166
1/2
✓ Branch 0 taken 3759348 times.
✗ Branch 1 not taken.
7518696 DBUG_TRACE;
4167 7518696 data_buf = nullptr;
4168
3/4
✓ Branch 0 taken 3697465 times.
✓ Branch 1 taken 61883 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3697464 times.
7518696 if (!is_valid()) return;
4169
4170 7518694 slave_proxy_id = thread_id;
4171 7518694 exec_time = query_exec_time;
4172
4173 7518694 ulong buf_len = catalog_len + 1 + time_zone_len + 1 + user_len + 1 +
4174 7518694 host_len + 1 + data_len + 1;
4175
4176
2/4
✓ Branch 0 taken 3759347 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3759347 times.
7518694 if (!(data_buf = (Log_event_header::Byte *)my_malloc(key_memory_log_event,
4177 buf_len, MYF(MY_WME)))) {
4178 common_header->set_is_valid(false);
4179 return;
4180 }
4181 /*
4182 The data buffer is used by the slave SQL thread while applying
4183 the event. The catalog, time_zone)str, user, host, db, query
4184 are pointers to this data_buf. The function call below, points these
4185 const pointers to the data buffer.
4186 */
4187
2/4
✓ Branch 0 taken 3759347 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3759347 times.
7518694 if (!(fill_data_buf(data_buf, buf_len))) {
4188 common_header->set_is_valid(false);
4189 return;
4190 }
4191
4192
2/4
✓ Branch 0 taken 3759347 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3759347 times.
✗ Branch 3 not taken.
7518694 common_header->set_is_valid(query != nullptr && q_len > 0);
4193
2/2
✓ Branch 0 taken 3759347 times.
✓ Branch 1 taken 1 times.
7518696 }
4194
4195 #ifndef MYSQL_SERVER
4196 /**
4197 Given a timestamp (microseconds since epoch), generate a string
4198 of the form YYYY-MM-DD HH:MM:SS.UUUUUU and return the length.
4199
4200 @param timestamp timestamp to convert to string.
4201 @param buf Buffer to which timestamp will be written as a string.
4202 @return The length of the string containing the converted timestamp
4203 */
4204 45392 inline size_t microsecond_timestamp_to_str(ulonglong timestamp, char *buf) {
4205 45392 time_t seconds = (time_t)(timestamp / 1000000);
4206 45392 int useconds = (int)(timestamp % 1000000);
4207 struct tm time_struct;
4208 45392 localtime_r(&seconds, &time_struct);
4209 45392 size_t length = strftime(buf, 255, "%F %T", &time_struct);
4210 45392 length += sprintf(buf + length, ".%06d", useconds);
4211 45392 length += strftime(buf + length, 255, " %Z", &time_struct);
4212 45392 return length;
4213 }
4214
4215 /**
4216 Query_log_event::print().
4217
4218 @todo
4219 print the catalog ??
4220 */
4221 56559 void Query_log_event::print_query_header(
4222 IO_CACHE *file, PRINT_EVENT_INFO *print_event_info) const {
4223 // TODO: print the catalog ??
4224 char buff[48], *end; // Enough for "SET TIMESTAMP=1305535348.123456"
4225 char quoted_id[1 + 2 * FN_REFLEN + 2];
4226 56559 size_t quoted_len = 0;
4227 56559 bool different_db = true;
4228 uint32 tmp;
4229
4230
2/2
✓ Branch 0 taken 55127 times.
✓ Branch 1 taken 1432 times.
56559 if (!print_event_info->short_form) {
4231 55127 const char xid_assign[] = "\tXid = ";
4232 55127 char xid_buf[64 + sizeof(xid_assign) - 1] = {0};
4233
2/2
✓ Branch 0 taken 3209 times.
✓ Branch 1 taken 51918 times.
55127 if (ddl_xid != binary_log::INVALID_XID) {
4234 3209 strcpy(xid_buf, xid_assign);
4235
1/2
✓ Branch 0 taken 3209 times.
✗ Branch 1 not taken.
3209 longlong10_to_str(ddl_xid, xid_buf + strlen(xid_assign), 10);
4236 }
4237
1/2
✓ Branch 0 taken 55127 times.
✗ Branch 1 not taken.
55127 print_header(file, print_event_info, false);
4238
1/2
✓ Branch 0 taken 55127 times.
✗ Branch 1 not taken.
55127 my_b_printf(file, "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d%s\n",
4239 55127 get_type_str(), (ulong)thread_id, (ulong)exec_time, error_code,
4240 xid_buf);
4241 }
4242
4243
2/2
✓ Branch 0 taken 21452 times.
✓ Branch 1 taken 35107 times.
56559 if ((common_header->flags & LOG_EVENT_SUPPRESS_USE_F)) {
4244
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 21196 times.
21452 if (!is_trans_keyword()) print_event_info->db[0] = '\0';
4245
1/2
✓ Branch 0 taken 35107 times.
✗ Branch 1 not taken.
35107 } else if (db) {
4246
1/2
✓ Branch 0 taken 35107 times.
✗ Branch 1 not taken.
35107 quoted_len = my_strmov_quoted_identifier((char *)quoted_id, db);
4247 35107 quoted_id[quoted_len] = '\0';
4248 35107 different_db = memcmp(print_event_info->db, db, db_len + 1);
4249
2/2
✓ Branch 0 taken 1606 times.
✓ Branch 1 taken 33501 times.
35107 if (different_db) memcpy(print_event_info->db, db, db_len + 1);
4250
4/4
✓ Branch 0 taken 34933 times.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 1435 times.
✓ Branch 3 taken 33498 times.
35107 if (db[0] && different_db)
4251
1/2
✓ Branch 0 taken 1435 times.
✗ Branch 1 not taken.
1435 my_b_printf(file, "use %s%s\n", quoted_id, print_event_info->delimiter);
4252 }
4253
4254
1/2
✓ Branch 0 taken 56559 times.
✗ Branch 1 not taken.
56559 end = longlong10_to_str(common_header->when.tv_sec,
4255 my_stpcpy(buff, "SET TIMESTAMP="), 10);
4256
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 56489 times.
56559 if (common_header->when.tv_usec)
4257 70 end += sprintf(end, ".%06d", (int)common_header->when.tv_usec);
4258 56559 end = my_stpcpy(end, print_event_info->delimiter);
4259 56559 *end++ = '\n';
4260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56559 times.
56559 assert(end < buff + sizeof(buff));
4261 [[maybe_unused]]
4262
1/2
✓ Branch 0 taken 56559 times.
✗ Branch 1 not taken.
56559 int write_res = my_b_write(file, (uchar *)buff, (uint)(end - buff));
4263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56559 times.
56559 assert(write_res == 0);
4264
2/2
✓ Branch 0 taken 56539 times.
✓ Branch 1 taken 20 times.
56559 if (!print_event_info->require_row_format &&
4265
2/2
✓ Branch 0 taken 52151 times.
✓ Branch 1 taken 4388 times.
56539 (!print_event_info->thread_id_printed ||
4266
2/2
✓ Branch 0 taken 568 times.
✓ Branch 1 taken 51583 times.
52151 ((common_header->flags & LOG_EVENT_THREAD_SPECIFIC_F) &&
4267
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 500 times.
568 thread_id != print_event_info->thread_id))) {
4268 // If --short-form, print deterministic value instead of pseudo_thread_id.
4269
1/2
✓ Branch 0 taken 4456 times.
✗ Branch 1 not taken.
4456 my_b_printf(file, "SET @@session.pseudo_thread_id=%lu%s\n",
4270 4280 short_form ? 999999999 : (ulong)thread_id,
4271
2/2
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 4280 times.
4456 print_event_info->delimiter);
4272 4456 print_event_info->thread_id = thread_id;
4273 4456 print_event_info->thread_id_printed = true;
4274 }
4275
4276 /*
4277 If flags2_inited==0, this is an event from 3.23 or 4.0; nothing to
4278 print (remember we don't produce mixed relay logs so there cannot be
4279 5.0 events before that one so there is nothing to reset).
4280 */
4281
1/2
✓ Branch 0 taken 56559 times.
✗ Branch 1 not taken.
56559 if (likely(flags2_inited)) /* likely as this will mainly read 5.0 logs */
4282 {
4283 /* tmp is a bitmask of bits which have changed. */
4284
2/2
✓ Branch 0 taken 52160 times.
✓ Branch 1 taken 4399 times.
56559 if (likely(print_event_info->flags2_inited))
4285 /* All bits which have changed */
4286 52160 tmp = (print_event_info->flags2) ^ flags2;
4287 else /* that's the first Query event we read */
4288 {
4289 4399 print_event_info->flags2_inited = true;
4290 4399 tmp = ~((uint32)0); /* all bits have changed */
4291 }
4292
4293
2/2
✓ Branch 0 taken 4405 times.
✓ Branch 1 taken 52154 times.
56559 if (unlikely(tmp)) /* some bits have changed */
4294 {
4295 4405 bool need_comma = false;
4296
1/2
✓ Branch 0 taken 4405 times.
✗ Branch 1 not taken.
4405 my_b_printf(file, "SET ");
4297
1/2
✓ Branch 0 taken 4405 times.
✗ Branch 1 not taken.
4405 print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2,
4298 "@@session.foreign_key_checks", &need_comma);
4299
1/2
✓ Branch 0 taken 4405 times.
✗ Branch 1 not taken.
4405 print_set_option(file, tmp, OPTION_AUTO_IS_NULL, flags2,
4300 "@@session.sql_auto_is_null", &need_comma);
4301
1/2
✓ Branch 0 taken 4405 times.
✗ Branch 1 not taken.
4405 print_set_option(file, tmp, OPTION_RELAXED_UNIQUE_CHECKS, ~flags2,
4302 "@@session.unique_checks", &need_comma);
4303
1/2
✓ Branch 0 taken 4405 times.
✗ Branch 1 not taken.
4405 print_set_option(file, tmp, OPTION_NOT_AUTOCOMMIT, ~flags2,
4304 "@@session.autocommit", &need_comma);
4305
1/2
✓ Branch 0 taken 4405 times.
✗ Branch 1 not taken.
4405 my_b_printf(file, "%s\n", print_event_info->delimiter);
4306 4405 print_event_info->flags2 = flags2;
4307 }
4308 }
4309
4310 /*
4311 Now the session variables;
4312 it's more efficient to pass SQL_MODE as a number instead of a
4313 comma-separated list.
4314 FOREIGN_KEY_CHECKS, SQL_AUTO_IS_NULL, UNIQUE_CHECKS are session-only
4315 variables (they have no global version; they're not listed in
4316 sql_class.h), The tests below work for pure binlogs or pure relay
4317 logs. Won't work for mixed relay logs but we don't create mixed
4318 relay logs (that is, there is no relay log with a format change
4319 except within the 3 first events, which mysqlbinlog handles
4320 gracefully). So this code should always be good.
4321 */
4322
4323
5/6
✓ Branch 0 taken 56559 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4923 times.
✓ Branch 3 taken 51636 times.
✓ Branch 4 taken 4923 times.
✓ Branch 5 taken 51636 times.
113118 if (likely(sql_mode_inited) &&
4324
2/2
✓ Branch 0 taken 51650 times.
✓ Branch 1 taken 4909 times.
108209 (unlikely(print_event_info->sql_mode != sql_mode ||
4325
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 51636 times.
51650 !print_event_info->sql_mode_inited))) {
4326 /*
4327 All the SQL_MODEs included in 0x1003ff00 were removed in 8.0.5. The
4328 upgrade procedure clears these bits. So the bits can only be set on older
4329 binlogs. Therefore, we generate this version-conditioned expression that
4330 masks out the removed modes in case this is executed on 8.0.5 or later.
4331 */
4332 4923 const char *mask = "";
4333
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 4887 times.
4923 if (sql_mode & 0x1003ff00) mask = "/*!80005 &~0x1003ff00*/";
4334 4923 my_b_printf(file, "SET @@session.sql_mode=%lu%s%s\n", (ulong)sql_mode, mask,
4335
1/2
✓ Branch 0 taken 4923 times.
✗ Branch 1 not taken.
4923 print_event_info->delimiter);
4336 4923 print_event_info->sql_mode = sql_mode;
4337 4923 print_event_info->sql_mode_inited = true;
4338 }
4339
2/2
✓ Branch 0 taken 52146 times.
✓ Branch 1 taken 4413 times.
56559 if (print_event_info->auto_increment_increment != auto_increment_increment ||
4340
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 52110 times.
52146 print_event_info->auto_increment_offset != auto_increment_offset) {
4341 4449 my_b_printf(file,
4342 "SET @@session.auto_increment_increment=%u, "
4343 "@@session.auto_increment_offset=%u%s\n",
4344 4449 auto_increment_increment, auto_increment_offset,
4345
1/2
✓ Branch 0 taken 4449 times.
✗ Branch 1 not taken.
4449 print_event_info->delimiter);
4346 4449 print_event_info->auto_increment_increment = auto_increment_increment;
4347 4449 print_event_info->auto_increment_offset = auto_increment_offset;
4348 }
4349
4350 /* TODO: print the catalog when we feature SET CATALOG */
4351
4352
5/6
✓ Branch 0 taken 56559 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4415 times.
✓ Branch 3 taken 52144 times.
✓ Branch 4 taken 4415 times.
✓ Branch 5 taken 52144 times.
113118 if (likely(charset_inited) &&
4353
2/2
✓ Branch 0 taken 52160 times.
✓ Branch 1 taken 4399 times.
108719 (unlikely(!print_event_info->charset_inited ||
4354
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 52144 times.
52160 memcmp(print_event_info->charset, charset, 6)))) {
4355 4415 const char *charset_p = charset; // Avoid type-punning warning.
4356
1/2
✓ Branch 0 taken 4415 times.
✗ Branch 1 not taken.
4415 CHARSET_INFO *cs_info = get_charset(uint2korr(charset_p), MYF(MY_WME));
4357
1/2
✓ Branch 0 taken 4415 times.
✗ Branch 1 not taken.
4415 if (cs_info) {
4358 /* for mysql client */
4359 4415 my_b_printf(file, "/*!\\C %s */%s\n", cs_info->csname,
4360
1/2
✓ Branch 0 taken 4415 times.
✗ Branch 1 not taken.
4415 print_event_info->delimiter);
4361 }
4362
1/2
✓ Branch 0 taken 4415 times.
✗ Branch 1 not taken.
4415 my_b_printf(file,
4363 "SET "
4364 "@@session.character_set_client=%d,"
4365 "@@session.collation_connection=%d,"
4366 "@@session.collation_server=%d"
4367 "%s\n",
4368 4415 uint2korr(charset_p), uint2korr(charset + 2),
4369 4415 uint2korr(charset + 4), print_event_info->delimiter);
4370 4415 memcpy(print_event_info->charset, charset, 6);
4371 4415 print_event_info->charset_inited = true;
4372 }
4373
2/2
✓ Branch 0 taken 1160 times.
✓ Branch 1 taken 55399 times.
56559 if (time_zone_len) {
4374 1160 if (memcmp(print_event_info->time_zone_str, time_zone_str,
4375
2/2
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 698 times.
1160 time_zone_len + 1)) {
4376 462 my_b_printf(file, "SET @@session.time_zone='%s'%s\n", time_zone_str,
4377
1/2
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
462 print_event_info->delimiter);
4378 462 memcpy(print_event_info->time_zone_str, time_zone_str, time_zone_len + 1);
4379 }
4380 }
4381
2/2
✓ Branch 0 taken 4401 times.
✓ Branch 1 taken 52158 times.
56559 if (lc_time_names_number != print_event_info->lc_time_names_number) {
4382 4401 my_b_printf(file, "SET @@session.lc_time_names=%d%s\n",
4383
1/2
✓ Branch 0 taken 4401 times.
✗ Branch 1 not taken.
4401 lc_time_names_number, print_event_info->delimiter);
4384 4401 print_event_info->lc_time_names_number = lc_time_names_number;
4385 }
4386
2/2
✓ Branch 0 taken 4405 times.
✓ Branch 1 taken 52154 times.
56559 if (charset_database_number != print_event_info->charset_database_number) {
4387
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4398 times.
4405 if (charset_database_number)
4388 7 my_b_printf(file, "SET @@session.collation_database=%d%s\n",
4389
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 charset_database_number, print_event_info->delimiter);
4390 else
4391 4398 my_b_printf(file, "SET @@session.collation_database=DEFAULT%s\n",
4392
1/2
✓ Branch 0 taken 4398 times.
✗ Branch 1 not taken.
4398 print_event_info->delimiter);
4393 4405 print_event_info->charset_database_number = charset_database_number;
4394 }
4395
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 56532 times.
56559 if (explicit_defaults_ts != TERNARY_UNSET)
4396 27 my_b_printf(file, "SET @@session.explicit_defaults_for_timestamp=%d%s\n",
4397 27 explicit_defaults_ts == TERNARY_OFF ? 0 : 1,
4398
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 print_event_info->delimiter);
4399 56559 if (default_collation_for_utf8mb4_number !=
4400
2/2
✓ Branch 0 taken 4399 times.
✓ Branch 1 taken 52160 times.
56559 print_event_info->default_collation_for_utf8mb4_number) {
4401
2/2
✓ Branch 0 taken 4382 times.
✓ Branch 1 taken 17 times.
4399 if (default_collation_for_utf8mb4_number)
4402 4382 my_b_printf(
4403 file, "/*!80011 SET @@session.default_collation_for_utf8mb4=%d*/%s\n",
4404
1/2
✓ Branch 0 taken 4382 times.
✗ Branch 1 not taken.
4382 default_collation_for_utf8mb4_number, print_event_info->delimiter);
4405 4399 print_event_info->default_collation_for_utf8mb4_number =
4406 4399 default_collation_for_utf8mb4_number;
4407 }
4408
2/2
✓ Branch 0 taken 1665 times.
✓ Branch 1 taken 54894 times.
56559 if (sql_require_primary_key != print_event_info->sql_require_primary_key) {
4409 1665 my_b_printf(file, "/*!80013 SET @@session.sql_require_primary_key=%d*/%s\n",
4410
1/2
✓ Branch 0 taken 1665 times.
✗ Branch 1 not taken.
1665 sql_require_primary_key, print_event_info->delimiter);
4411 }
4412
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 56433 times.
56559 if (default_table_encryption != print_event_info->default_table_encryption) {
4413 126 my_b_printf(file,
4414 "/*!80016 SET @@session.default_table_encryption=%d*/%s\n",
4415
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 default_table_encryption, print_event_info->delimiter);
4416 }
4417 56559 }
4418
4419 56523 void Query_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
4420 56523 IO_CACHE *const head = &print_event_info->head_cache;
4421
4422 /**
4423 reduce the size of io cache so that the write function is called
4424 for every call to my_b_write().
4425 */
4426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56523 times.
56523 DBUG_EXECUTE_IF("simulate_file_write_error",
4427 { head->write_pos = head->write_end - 500; });
4428 56523 print_query_header(head, print_event_info);
4429 [[maybe_unused]]
4430 56523 int write_res = my_b_write(head, pointer_cast<const uchar *>(query), q_len);
4431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56523 times.
56523 assert(write_res == 0);
4432 56523 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
4433 56523 }
4434 #endif /* !MYSQL_SERVER */
4435
4436 #if defined(MYSQL_SERVER)
4437
4438 /**
4439 Associating slave Worker thread to a subset of temporary tables.
4440
4441 @param thd_arg THD instance pointer
4442 @param rli Relay_log_info of the worker
4443 */
4444 567302 void Query_log_event::attach_temp_tables_worker(THD *thd_arg,
4445 const Relay_log_info *rli) {
4446
2/2
✓ Branch 0 taken 567462 times.
✓ Branch 1 taken 4 times.
567302 if (!is_skip_temp_tables_handling_by_worker())
4447 567462 rli->current_mts_submode->attach_temp_tables(thd_arg, rli, this);
4448 567551 }
4449
4450 /**
4451 Dissociating slave Worker thread from its thd->temporary_tables
4452 to possibly update the involved entries of db-to-worker hash
4453 with new values of temporary_tables.
4454
4455 @param thd_arg THD instance pointer
4456 @param rli relay log info of the worker thread
4457 */
4458 3212 void Query_log_event::detach_temp_tables_worker(THD *thd_arg,
4459 const Relay_log_info *rli) {
4460
1/2
✓ Branch 0 taken 3212 times.
✗ Branch 1 not taken.
3212 if (!is_skip_temp_tables_handling_by_worker())
4461 3212 rli->current_mts_submode->detach_temp_tables(thd_arg, rli, this);
4462 3212 }
4463
4464 /*
4465 Query_log_event::do_apply_event()
4466 */
4467 567440 int Query_log_event::do_apply_event(Relay_log_info const *rli) {
4468 567440 return do_apply_event(rli, query, q_len);
4469 }
4470
4471 /*
4472 is_silent_error
4473
4474 Return true if the thread has an error which should be
4475 handled silently
4476 */
4477
4478 296 static bool is_silent_error(THD *thd) {
4479
1/2
✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
296 DBUG_TRACE;
4480 Diagnostics_area::Sql_condition_iterator it =
4481
1/2
✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
296 thd->get_stmt_da()->sql_conditions();
4482 const Sql_condition *err;
4483
3/4
✓ Branch 0 taken 615 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 319 times.
✓ Branch 3 taken 296 times.
615 while ((err = it++)) {
4484
3/8
✓ Branch 0 taken 319 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 319 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 319 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
319 DBUG_PRINT("info", ("has condition %d %s", err->mysql_errno(),
4485 err->message_text()));
4486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 319 times.
319 switch (err->mysql_errno()) {
4487 case ER_SLAVE_SILENT_RETRY_TRANSACTION: {
4488 return true;
4489 }
4490 319 default:
4491 319 break;
4492 }
4493 }
4494 296 return false;
4495 296 }
4496
4497 /**
4498 @todo
4499 Compare the values of "affected rows" around here. Something
4500 like:
4501 @code
4502 if ((uint32) affected_in_event != (uint32) affected_on_slave)
4503 {
4504 sql_print_error("Slave: did not get the expected number of affected "
4505 "rows running query from master - expected %d, got %d (this numbers "
4506 "should have matched modulo 4294967296).", 0, ...);
4507 thd->query_error = 1;
4508 }
4509 @endcode
4510 We may also want an option to tell the slave to ignore "affected"
4511 mismatch. This mismatch could be implemented with a new ER_ code, and
4512 to ignore it you would use --replica-skip-errors...
4513 */
4514 567540 int Query_log_event::do_apply_event(Relay_log_info const *rli,
4515 const char *query_arg, size_t q_len_arg) {
4516
1/2
✓ Branch 0 taken 567638 times.
✗ Branch 1 not taken.
567540 DBUG_TRACE;
4517 567638 int expected_error, actual_error = 0;
4518
4519
3/8
✓ Branch 0 taken 567638 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 567651 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 567651 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
567638 DBUG_PRINT("info", ("query=%s, q_len_arg=%lu", query,
4520 static_cast<unsigned long>(q_len_arg)));
4521
4522 /*
4523 Colleagues: please never free(thd->catalog) in MySQL. This would
4524 lead to bugs as here thd->catalog is a part of an allocated block,
4525 not an entire allocated block (see
4526 Query_log_event::do_apply_event()). Same for thd->db().str. Thank
4527 you.
4528 */
4529
4530
2/2
✓ Branch 0 taken 527702 times.
✓ Branch 1 taken 39918 times.
567620 if (catalog_len) {
4531 527702 LEX_CSTRING catalog_lex_cstr = {catalog, catalog_len};
4532 527702 thd->set_catalog(catalog_lex_cstr);
4533 } else
4534 39918 thd->set_catalog(EMPTY_CSTR);
4535
4536 bool need_inc_rewrite_db_filter_counter;
4537 size_t valid_len;
4538 bool len_error;
4539 bool is_invalid_db_name =
4540
1/2
✓ Branch 0 taken 567627 times.
✗ Branch 1 not taken.
567617 validate_string(system_charset_info, db, db_len, &valid_len, &len_error);
4541
4542
3/12
✓ Branch 0 taken 567617 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 567645 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 567645 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
567627 DBUG_PRINT("debug", ("is_invalid_db_name= %s, valid_len=%zu, len_error=%s",
4543 is_invalid_db_name ? "true" : "false", valid_len,
4544 len_error ? "true" : "false"));
4545
4546
3/4
✓ Branch 0 taken 567552 times.
✓ Branch 1 taken 93 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 567559 times.
567645 if (is_invalid_db_name || len_error) {
4547 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4548
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
86 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
4549 "Invalid database name in Query event.");
4550 thd->is_slave_error = true;
4551 goto end;
4552 }
4553
4554
1/2
✓ Branch 0 taken 567644 times.
✗ Branch 1 not taken.
567559 need_inc_rewrite_db_filter_counter = set_thd_db(thd, db, db_len);
4555
4556 /*
4557 Setting the character set and collation of the current database thd->db.
4558 */
4559
2/4
✓ Branch 0 taken 567537 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 567537 times.
567644 if (get_default_db_collation(thd, thd->db().str, &thd->db_charset)) {
4560 assert(thd->is_error() || thd->killed);
4561 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
4562 "Error in get_default_db_collation: %s",
4563 thd->get_stmt_da()->message_text());
4564 thd->is_slave_error = true;
4565 goto end;
4566 }
4567
4568
1/2
✓ Branch 0 taken 567586 times.
✗ Branch 1 not taken.
567537 thd->db_charset = thd->db_charset ? thd->db_charset : thd->collation();
4569
4570 567586 thd->variables.auto_increment_increment = auto_increment_increment;
4571 567586 thd->variables.auto_increment_offset = auto_increment_offset;
4572
2/2
✓ Branch 0 taken 16605 times.
✓ Branch 1 taken 550981 times.
567586 if (explicit_defaults_ts != TERNARY_UNSET)
4573 16605 thd->variables.explicit_defaults_for_timestamp =
4574 16605 explicit_defaults_ts == TERNARY_OFF ? false : true;
4575
4576 /*
4577 todo: such cleanup should not be specific to Query event and therefore
4578 is preferable at a common with other event pre-execution point
4579 */
4580
1/2
✓ Branch 0 taken 567645 times.
✗ Branch 1 not taken.
567586 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
4581
1/2
✓ Branch 0 taken 567642 times.
✗ Branch 1 not taken.
567645 thd->get_stmt_da()->reset_diagnostics_area();
4582 567642 thd->get_stmt_da()->reset_statement_cond_count();
4583
4584
3/4
✓ Branch 0 taken 96713 times.
✓ Branch 1 taken 470677 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 96713 times.
567390 if (strcmp("COMMIT", query) == 0 && rli->tables_to_lock != nullptr) {
4585 /*
4586 Cleaning-up the last statement context:
4587 the terminal event of the current statement flagged with
4588 STMT_END_F got filtered out in ndb circular replication.
4589 */
4590 int error;
4591 char llbuff[22];
4592 if ((error =
4593 rows_event_stmt_cleanup(const_cast<Relay_log_info *>(rli), thd))) {
4594 const_cast<Relay_log_info *>(rli)->report(
4595 ERROR_LEVEL, error,
4596 "Error in cleaning up after an event preceding the commit; "
4597 "the group log file/position: %s %s",
4598 const_cast<Relay_log_info *>(rli)->get_group_master_log_name_info(),
4599 llstr(const_cast<Relay_log_info *>(rli)
4600 ->get_group_master_log_pos_info(),
4601 llbuff));
4602 }
4603 /*
4604 Executing a part of rli->stmt_done() logics that does not deal
4605 with group position change. The part is redundant now but is
4606 future-change-proof addon, e.g if COMMIT handling will start checking
4607 invariants like IN_STMT flag must be off at committing the transaction.
4608 */
4609 const_cast<Relay_log_info *>(rli)->inc_event_relay_log_pos();
4610 const_cast<Relay_log_info *>(rli)->clear_flag(Relay_log_info::IN_STMT);
4611 } else {
4612
1/2
✓ Branch 0 taken 567611 times.
✗ Branch 1 not taken.
567390 const_cast<Relay_log_info *>(rli)->slave_close_thread_tables(thd);
4613 }
4614
4615 {
4616
1/2
✓ Branch 0 taken 567406 times.
✗ Branch 1 not taken.
567611 Applier_security_context_guard security_context{rli, thd};
4617
2/2
✓ Branch 0 taken 531938 times.
✓ Branch 1 taken 35468 times.
567406 if (!thd->variables.require_row_format) {
4618
1/2
✓ Branch 0 taken 531922 times.
✗ Branch 1 not taken.
531938 if (!security_context.skip_priv_checks() &&
4619
3/4
✓ Branch 0 taken 321 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 154 times.
✓ Branch 3 taken 167 times.
321 !security_context.has_access({SUPER_ACL}) &&
4620
5/6
✓ Branch 0 taken 321 times.
✓ Branch 1 taken 531601 times.
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 131 times.
✓ Branch 5 taken 23 times.
532252 !security_context.has_access({"SYSTEM_VARIABLES_ADMIN"}) &&
4621
4/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 531790 times.
531931 !security_context.has_access({"SESSION_VARIABLES_ADMIN"})) {
4622
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 rli->report(ERROR_LEVEL, ER_SPECIFIC_ACCESS_DENIED_ERROR,
4623
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 ER_THD(thd, ER_SPECIFIC_ACCESS_DENIED_ERROR),
4624 "SUPER, SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN");
4625 10 thd->is_slave_error = true;
4626 10 goto end;
4627 }
4628 531790 thd->variables.pseudo_thread_id = thread_id; // for temp tables
4629 }
4630
4631
1/2
✓ Branch 0 taken 567466 times.
✗ Branch 1 not taken.
567258 thd->set_time(&(common_header->when));
4632
1/2
✓ Branch 0 taken 567644 times.
✗ Branch 1 not taken.
567466 thd->set_query(query_arg, q_len_arg);
4633
1/2
✓ Branch 0 taken 567567 times.
✗ Branch 1 not taken.
567644 thd->set_query_for_display(query_arg, q_len_arg);
4634
1/2
✓ Branch 0 taken 567539 times.
✗ Branch 1 not taken.
567567 thd->set_query_id(next_query_id());
4635
1/2
✓ Branch 0 taken 567588 times.
✗ Branch 1 not taken.
567539 attach_temp_tables_worker(thd, rli);
4636
3/10
✓ Branch 0 taken 567619 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 567588 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 567588 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
567588 DBUG_PRINT("query", ("%s", thd->query().str));
4637
4638
3/4
✓ Branch 0 taken 567556 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 567553 times.
567588 DBUG_EXECUTE_IF("simulate_error_in_ddl", error_code = 1051;);
4639
4640
3/6
✓ Branch 0 taken 567453 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 567467 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 567528 times.
✗ Branch 5 not taken.
1134999 if (ignored_error_code((expected_error = error_code)) ||
4641
1/2
✓ Branch 0 taken 567478 times.
✗ Branch 1 not taken.
567467 !unexpected_error_code(expected_error)) {
4642
2/2
✓ Branch 0 taken 567519 times.
✓ Branch 1 taken 9 times.
567528 if (flags2_inited)
4643 /*
4644 all bits of thd->variables.option_bits which are 1 in
4645 OPTIONS_WRITTEN_TO_BIN_LOG must take their value from flags2.
4646 */
4647 567519 thd->variables.option_bits =
4648 567519 flags2 | (thd->variables.option_bits & ~OPTIONS_WRITTEN_TO_BIN_LOG);
4649 /*
4650 else, we are in a 3.23/4.0 binlog; we previously received a
4651 Rotate_log_event which reset thd->variables.option_bits and sql_mode
4652 etc, so nothing to do.
4653 */
4654 /*
4655 We do not replicate MODE_NO_DIR_IN_CREATE. That is, if the master is a
4656 slave which runs with SQL_MODE=MODE_NO_DIR_IN_CREATE, this should not
4657 force us to ignore the dir too. Imagine you are a ring of machines, and
4658 one has a disk problem so that you temporarily need
4659 MODE_NO_DIR_IN_CREATE on this machine; you don't want it to propagate
4660 elsewhere (you don't want all slaves to start ignoring the dirs).
4661 */
4662
1/2
✓ Branch 0 taken 567564 times.
✗ Branch 1 not taken.
567528 if (sql_mode_inited) {
4663 /*
4664 All the SQL_MODEs included in 0x1003ff00 were removed in 8.0.5.
4665 The upgrade procedure clears these bits. So the bits can only be set
4666 when replicating from an older server. We consider it safe to clear
4667 the bits, because:
4668 (1) all these bits except MAXDB has zero impact on replicated
4669 statements, and MAXDB has minimal impact only;
4670 (2) the upgrade-pre-check script warns when the bit is set, so we
4671 assume users have verified that it is safe to ignore the bit.
4672 */
4673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 567564 times.
567564 if (sql_mode & ~(MODE_ALLOWED_MASK | MODE_IGNORED_MASK)) {
4674 my_error(ER_UNSUPPORTED_SQL_MODE, MYF(0),
4675 sql_mode & ~(MODE_ALLOWED_MASK | MODE_IGNORED_MASK));
4676 1 goto compare_errors;
4677 }
4678 567564 sql_mode &= MODE_ALLOWED_MASK;
4679 567564 thd->variables.sql_mode =
4680 567564 (sql_mode_t)((thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) |
4681 567564 (sql_mode & ~(ulonglong)MODE_NO_DIR_IN_CREATE));
4682 }
4683
2/2
✓ Branch 0 taken 567513 times.
✓ Branch 1 taken 15 times.
567528 if (charset_inited) {
4684
3/4
✓ Branch 0 taken 567595 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11665 times.
✓ Branch 3 taken 555930 times.
567513 if (rli->cached_charset_compare(charset)) {
4685 11665 const char *charset_p = charset; // Avoid type-punning warning.
4686 /* Verify that we support the charsets found in the event. */
4687 34995 if (!(thd->variables.character_set_client =
4688
1/2
✓ Branch 0 taken 11665 times.
✗ Branch 1 not taken.
11665 get_charset(uint2korr(charset_p), MYF(MY_WME))) ||
4689 23330 !(thd->variables.collation_connection =
4690
4/8
✓ Branch 0 taken 11665 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11665 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11665 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 11665 times.
23330 get_charset(uint2korr(charset + 2), MYF(MY_WME))) ||
4691 23330 !(thd->variables.collation_server =
4692
2/4
✓ Branch 0 taken 11665 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11665 times.
11665 get_charset(uint2korr(charset + 4), MYF(MY_WME)))) {
4693 /*
4694 We updated the thd->variables with nonsensical values (0). Let's
4695 set them to something safe (i.e. which avoids crash), and we'll
4696 stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to
4697 ignore this error).
4698 */
4699 set_slave_thread_default_charset(thd, rli);
4700 goto compare_errors;
4701 }
4702
1/2
✓ Branch 0 taken 11665 times.
✗ Branch 1 not taken.
11665 thd->update_charset(); // for the charset change to take effect
4703 /*
4704 We cannot ask for parsing a statement using a character set
4705 without state_maps (parser internal data).
4706 */
4707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11665 times.
11665 if (!thd->variables.character_set_client->state_maps) {
4708 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4709 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
4710 "character_set cannot be parsed");
4711 thd->is_slave_error = true;
4712 goto end;
4713 }
4714 /*
4715 Reset thd->query_string.cs to the newly set value.
4716 Note, there is a small flaw here. For a very short time frame
4717 if the new charset is different from the old charset and
4718 if another thread executes "SHOW PROCESSLIST" after
4719 the above thd->set_query() and before this thd->set_query(),
4720 and if the current query has some non-ASCII characters,
4721 the another thread may see some '?' marks in the PROCESSLIST
4722 result. This should be acceptable now. This is a reminder
4723 to fix this if any refactoring happens here sometime.
4724 */
4725
1/2
✓ Branch 0 taken 11665 times.
✗ Branch 1 not taken.
11665 thd->set_query(query_arg, q_len_arg);
4726
1/2
✓ Branch 0 taken 11465 times.
✗ Branch 1 not taken.
11665 thd->reset_query_for_display();
4727 }
4728 }
4729
2/2
✓ Branch 0 taken 21170 times.
✓ Branch 1 taken 546240 times.
567410 if (time_zone_len) {
4730 21170 String tmp(time_zone_str, time_zone_len, &my_charset_bin);
4731
3/4
✓ Branch 0 taken 21170 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 21169 times.
21170 if (!(thd->variables.time_zone = my_tz_find(thd, &tmp))) {
4732
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), tmp.c_ptr());
4733 1 thd->variables.time_zone = global_system_variables.time_zone;
4734 1 goto compare_errors;
4735 }
4736
2/2
✓ Branch 0 taken 21169 times.
✓ Branch 1 taken 1 times.
21170 }
4737
2/2
✓ Branch 0 taken 1023 times.
✓ Branch 1 taken 566386 times.
567409 if (lc_time_names_number) {
4738 2046 if (!(thd->variables.lc_time_names =
4739
2/4
✓ Branch 0 taken 1023 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1023 times.
1023 my_locale_by_number(lc_time_names_number))) {
4740 my_printf_error(ER_UNKNOWN_ERROR, "Unknown locale: '%d'", MYF(0),
4741 lc_time_names_number);
4742 thd->variables.lc_time_names = &my_locale_en_US;
4743 goto compare_errors;
4744 }
4745 } else
4746 566386 thd->variables.lc_time_names = &my_locale_en_US;
4747
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 566797 times.
567409 if (charset_database_number) {
4748 CHARSET_INFO *cs;
4749
2/4
✓ Branch 0 taken 612 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 612 times.
612 if (!(cs = get_charset(charset_database_number, MYF(0)))) {
4750 char buf[20];
4751 longlong10_to_str(charset_database_number, buf, 10);
4752 my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
4753 goto compare_errors;
4754 }
4755 612 thd->variables.collation_database = cs;
4756 } else
4757 566797 thd->variables.collation_database = thd->db_charset;
4758
2/2
✓ Branch 0 taken 567329 times.
✓ Branch 1 taken 80 times.
567409 if (default_collation_for_utf8mb4_number) {
4759 CHARSET_INFO *cs;
4760
2/4
✓ Branch 0 taken 567333 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 567333 times.
567329 if (!(cs = get_charset(default_collation_for_utf8mb4_number, MYF(0)))) {
4761 char buf[20];
4762 longlong10_to_str(default_collation_for_utf8mb4_number, buf, 10);
4763 my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
4764 goto compare_errors;
4765 }
4766 567333 thd->variables.default_collation_for_utf8mb4 = cs;
4767 } else
4768 // The transaction was replicated from a server with utf8mb4_general_ci
4769 // as default collation for utf8mb4 (versions 5.7-)
4770 80 thd->variables.default_collation_for_utf8mb4 =
4771 &my_charset_utf8mb4_general_ci;
4772
4773
4/4
✓ Branch 0 taken 11007 times.
✓ Branch 1 taken 556406 times.
✓ Branch 2 taken 11002 times.
✓ Branch 3 taken 556411 times.
578420 if (sql_require_primary_key != 0xff &&
4774 Relay_log_info::PK_CHECK_STREAM ==
4775
3/4
✓ Branch 0 taken 11007 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11002 times.
✓ Branch 3 taken 5 times.
11007 rli->get_require_table_primary_key_check()) {
4776
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11002 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
11002 assert(sql_require_primary_key == 0 || sql_require_primary_key == 1);
4777
1/2
✓ Branch 0 taken 11002 times.
✗ Branch 1 not taken.
11002 if (!security_context.skip_priv_checks() &&
4778
3/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 17 times.
28 !security_context.has_access({SUPER_ACL}) &&
4779
5/6
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 10974 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 3 times.
11038 !security_context.has_access({"SYSTEM_VARIABLES_ADMIN"}) &&
4780
5/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 11001 times.
11010 !security_context.has_access({"SESSION_VARIABLES_ADMIN"})) {
4781
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report(
4782 ERROR_LEVEL, ER_SPECIFIC_ACCESS_DENIED_ERROR,
4783
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ER_THD(thd, ER_SPECIFIC_ACCESS_DENIED_ERROR),
4784 "SUPER, SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN");
4785 1 thd->is_slave_error = true;
4786 1 goto end;
4787 }
4788 11001 thd->variables.sql_require_primary_key = sql_require_primary_key;
4789 }
4790
4791
2/2
✓ Branch 0 taken 882 times.
✓ Branch 1 taken 566530 times.
567412 if (default_table_encryption != 0xff) {
4792
3/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 860 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
882 assert(default_table_encryption == 0 || default_table_encryption == 1);
4793 1764 if (thd->variables.default_table_encryption !=
4794 907 static_cast<bool>(default_table_encryption) &&
4795
3/4
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 19 times.
25 !security_context.skip_priv_checks() &&
4796
4/6
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 857 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
913 !security_context.has_access({SUPER_ACL}) &&
4797
5/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 879 times.
888 !security_context.has_access(
4798 {"SYSTEM_VARIABLES_ADMIN", "TABLE_ENCRYPTION_ADMIN"})) {
4799
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 rli->report(
4800 ERROR_LEVEL, ER_SPECIFIC_ACCESS_DENIED_ERROR,
4801
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ER_THD(thd, ER_SPECIFIC_ACCESS_DENIED_ERROR),
4802 "SUPER or SYSTEM_VARIABLES_ADMIN and TABLE_ENCRYPTION_ADMIN");
4803 3 thd->is_slave_error = true;
4804 3 goto end;
4805 }
4806 879 thd->variables.default_table_encryption = default_table_encryption;
4807 }
4808
4809 567409 thd->table_map_for_update = (table_map)table_map_for_update;
4810
4811 567409 LEX_STRING user_lex = LEX_STRING();
4812 567409 LEX_STRING host_lex = LEX_STRING();
4813
2/2
✓ Branch 0 taken 4352 times.
✓ Branch 1 taken 563057 times.
567409 if (user) {
4814 4352 user_lex.str = const_cast<char *>(user);
4815 4352 user_lex.length = strlen(user);
4816 }
4817
2/2
✓ Branch 0 taken 4352 times.
✓ Branch 1 taken 563057 times.
567409 if (host) {
4818 4352 host_lex.str = const_cast<char *>(host);
4819 4352 host_lex.length = strlen(host);
4820 }
4821 567409 thd->set_invoker(&user_lex, &host_lex);
4822
4823 /*
4824 Flag if we need to rollback the statement transaction on
4825 slave if it by chance succeeds.
4826 If we expected a non-zero error code and get nothing and,
4827 it is a concurrency issue or ignorable issue, effects
4828 of the statement should be rolled back.
4829 */
4830
8/10
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 567089 times.
✓ Branch 2 taken 250 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 250 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 246 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 567335 times.
567581 if (expected_error && (ignored_error_code(expected_error) ||
4831 250 concurrency_error_code(expected_error))) {
4832 4 thd->variables.option_bits |= OPTION_MASTER_SQL_ERROR;
4833 }
4834
4835
1/2
✓ Branch 0 taken 567497 times.
✗ Branch 1 not taken.
567339 mysql_thread_set_secondary_engine(false);
4836
4837 /* Execute the query (note that we bypass dispatch_command()) */
4838
1/2
✓ Branch 0 taken 567503 times.
✗ Branch 1 not taken.
567497 Parser_state parser_state;
4839
4/8
✓ Branch 0 taken 567436 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 567581 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 567431 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 567466 times.
✗ Branch 7 not taken.
567503 if (!parser_state.init(thd, thd->query().str, thd->query().length)) {
4840 567466 parser_state.m_input.m_has_digest = true;
4841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 567466 times.
567466 assert(thd->m_digest == nullptr);
4842 567466 thd->m_digest = &thd->m_digest_state;
4843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 567466 times.
567466 assert(thd->m_statement_psi == nullptr);
4844
1/2
✓ Branch 0 taken 567511 times.
✗ Branch 1 not taken.
567466 thd->m_statement_psi = MYSQL_START_STATEMENT(
4845 &thd->m_statement_state, stmt_info_rpl.m_key, thd->db().str,
4846 thd->db().length, thd->charset(), nullptr);
4847
1/2
✓ Branch 0 taken 567500 times.
✗ Branch 1 not taken.
567511 THD_STAGE_INFO(thd, stage_starting);
4848
4849
1/2
✓ Branch 0 taken 567520 times.
✗ Branch 1 not taken.
567500 if (thd->m_digest != nullptr)
4850
1/2
✓ Branch 0 taken 567513 times.
✗ Branch 1 not taken.
567520 thd->m_digest->reset(thd->m_token_array, max_digest_length);
4851
4852 struct System_status_var query_start_status;
4853 567493 thd->clear_copy_status_var();
4854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 567193 times.
567193 if (opt_log_slow_extra) {
4855 thd->copy_status_var(&query_start_status);
4856 }
4857
4858
1/2
✓ Branch 0 taken 567239 times.
✗ Branch 1 not taken.
567193 dispatch_sql_command(thd, &parser_state, true);
4859
4860 567239 enum_sql_command command = thd->lex->sql_command;
4861
4862 /*
4863 Transaction isolation level of pure row based replicated transactions
4864 can be optimized to ISO_READ_COMMITTED by the applier when applying
4865 the Gtid_log_event.
4866
4867 If we are applying a statement other than transaction control ones
4868 after having optimized the transactions isolation level, we must warn
4869 about the non-standard situation we have found.
4870 */
4871
1/2
✓ Branch 0 taken 567112 times.
✗ Branch 1 not taken.
567239 if (is_sbr_logging_format() &&
4872
6/6
✓ Branch 0 taken 177827 times.
✓ Branch 1 taken 389285 times.
✓ Branch 2 taken 177458 times.
✓ Branch 3 taken 369 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 567111 times.
744570 thd->variables.transaction_isolation > ISO_READ_COMMITTED &&
4873
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 177457 times.
177458 thd->tx_isolation == ISO_READ_COMMITTED) {
4874 1 String message;
4875
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 message.append(
4876 "The isolation level for the current transaction "
4877 "was changed to READ_COMMITTED based on the "
4878 "assumption that it had only row events and was "
4879 "not mixed with statements. "
4880 "However, an unexpected statement was found in "
4881 "the middle of the transaction."
4882 "Query: '");
4883
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 message.append(thd->query().str);
4884
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 message.append("'");
4885
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4886
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ER_THD(thd, ER_SLAVE_FATAL_ERROR), message.c_ptr());
4887 1 thd->is_slave_error = true;
4888 1 goto end;
4889 1 }
4890
4891
7/8
✓ Branch 0 taken 567030 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 149818 times.
✓ Branch 3 taken 417212 times.
✓ Branch 4 taken 137811 times.
✓ Branch 5 taken 11994 times.
✓ Branch 6 taken 137823 times.
✓ Branch 7 taken 429194 times.
716916 if (sqlcom_can_generate_row_events(thd->lex->sql_command) &&
4892 149818 thd->get_row_count_func() > 0) {
4893
2/2
✓ Branch 0 taken 146171 times.
✓ Branch 1 taken 137774 times.
283945 for (TABLE_LIST *tbl = thd->lex->query_tables; tbl;
4894 146122 tbl = tbl->next_global) {
4895
6/6
✓ Branch 0 taken 146072 times.
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 146070 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 146070 times.
✓ Branch 5 taken 136 times.
146171 if (!tbl->is_placeholder() && tbl->table->file) {
4896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 145986 times.
146070 if (!tbl->table->file->rpl_can_handle_stm_event()) {
4897 String message;
4898
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 message.append(
4899 "Masters binlog format is not ROW and storage "
4900 "engine can not handle non-ROW events at this "
4901 "time. Table: '");
4902
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 message.append(tbl->get_db_name());
4903
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 message.append(".");
4904
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 message.append(tbl->get_table_name());
4905
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 message.append("' Query: '");
4906
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 message.append(thd->query().str);
4907
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 message.append("'");
4908
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4909
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ER_THD(thd, ER_SLAVE_FATAL_ERROR), message.c_ptr());
4910 2 thd->is_slave_error = true;
4911 2 goto end;
4912 2 }
4913 }
4914 }
4915 }
4916
4917 /*
4918 Do not need to increase rewrite_db_filter counter for
4919 SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_BEGIN and
4920 SQLCOM_COMMIT.
4921 */
4922
6/6
✓ Branch 0 taken 227 times.
✓ Branch 1 taken 566741 times.
✓ Branch 2 taken 214 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 199 times.
✓ Branch 5 taken 15 times.
566968 if (need_inc_rewrite_db_filter_counter && command != SQLCOM_CREATE_DB &&
4923
4/4
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 125 times.
✓ Branch 3 taken 12 times.
199 command != SQLCOM_DROP_DB && command != SQLCOM_BEGIN &&
4924 command != SQLCOM_COMMIT) {
4925 125 Rpl_filter *rpl_filter = thd->rli_slave->rpl_filter;
4926
1/2
✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
125 if (rpl_filter)
4927 125 rpl_filter->get_rewrite_db_statistics()->increase_counter();
4928 }
4929 /* Finalize server status flags after executing a statement. */
4930
1/2
✓ Branch 0 taken 567056 times.
✗ Branch 1 not taken.
566968 thd->update_slow_query_status();
4931
1/2
✓ Branch 0 taken 567310 times.
✗ Branch 1 not taken.
567056 log_slow_statement(thd);
4932 }
4933
4934 567275 thd->variables.option_bits &= ~OPTION_MASTER_SQL_ERROR;
4935
4936 /*
4937 Resetting the enable_slow_log thd variable.
4938
4939 We need to reset it back to the opt_log_slow_replica_statements
4940 value after the statement execution (and slow logging
4941 is done). It might have changed if the statement was an
4942 admin statement (in which case, down in dispatch_sql_command execution
4943 thd->enable_slow_log is set to the value of
4944 opt_log_slow_admin_statements).
4945 */
4946 567275 thd->enable_slow_log = opt_log_slow_replica_statements;
4947
1/2
✓ Branch 0 taken 567150 times.
✗ Branch 1 not taken.
567278 } else {
4948 /*
4949 The query got a really bad error on the master (thread killed etc),
4950 which could be inconsistent. Parse it to test the table names: if the
4951 replicate-*-do|ignore-table rules say "this query must be ignored" then
4952 we exit gracefully; otherwise we warn about the bad error and tell DBA
4953 to check/fix it.
4954 */
4955 if (mysql_test_parse_for_slave(thd))
4956
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 clear_all_errors(
4957 thd, const_cast<Relay_log_info *>(rli)); /* Can ignore query */
4958 else {
4959
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 rli->report(ERROR_LEVEL, ER_ERROR_ON_MASTER,
4960 2 ER_THD(thd, ER_ERROR_ON_MASTER), expected_error,
4961
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 thd->query().str);
4962 2 thd->is_slave_error = true;
4963 }
4964 5 goto end;
4965 }
4966 /* If the query was not ignored, it is printed to the general log */
4967
7/8
✓ Branch 0 taken 567314 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 873 times.
✓ Branch 3 taken 566441 times.
✓ Branch 4 taken 465 times.
✓ Branch 5 taken 314 times.
✓ Branch 6 taken 297 times.
✓ Branch 7 taken 566923 times.
567929 if (!thd->is_error() ||
4968 873 thd->get_stmt_da()->mysql_errno() != ER_SLAVE_IGNORED_TABLE) {
4969 /*
4970 Log the rewritten query if the query was rewritten
4971 and the option to log raw was not set.
4972
4973 There is an assumption here. We assume that query log
4974 events can never have multi-statement queries, thus the
4975 parsed statement is the same as the raw one.
4976 */
4977
6/8
✓ Branch 0 taken 566930 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 566938 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 565401 times.
✓ Branch 5 taken 1514 times.
✓ Branch 6 taken 565429 times.
✓ Branch 7 taken 1479 times.
566923 if (opt_general_log_raw || thd->rewritten_query().length() == 0)
4978
1/2
✓ Branch 0 taken 565587 times.
✗ Branch 1 not taken.
565420 query_logger.general_log_write(thd, COM_QUERY, thd->query().str,
4979
2/4
✓ Branch 0 taken 565444 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 565420 times.
✗ Branch 3 not taken.
565429 thd->query().length);
4980 else
4981
1/2
✓ Branch 0 taken 1535 times.
✗ Branch 1 not taken.
1535 query_logger.general_log_write(thd, COM_QUERY,
4982
1/2
✓ Branch 0 taken 1535 times.
✗ Branch 1 not taken.
1535 thd->rewritten_query().ptr(),
4983
1/2
✓ Branch 0 taken 1535 times.
✗ Branch 1 not taken.
1479 thd->rewritten_query().length());
4984 }
4985
4986 297 compare_errors:
4987 /* Parser errors shall be ignored when (GTID) skipping statements */
4988
3/4
✓ Branch 0 taken 567440 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 870 times.
568293 if (thd->is_error() &&
4989
4/4
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 566566 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 567437 times.
568313 thd->get_stmt_da()->mysql_errno() == ER_PARSE_ERROR &&
4990
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
3 gtid_pre_statement_checks(thd) == GTID_STATEMENT_SKIP) {
4991
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
2 thd->get_stmt_da()->reset_diagnostics_area();
4992 }
4993 /*
4994 In the slave thread, we may sometimes execute some DROP / * 40005
4995 TEMPORARY * / TABLE that come from parts of binlogs (likely if we
4996 use RESET SLAVE or CHANGE MASTER TO), while the temporary table
4997 has already been dropped. To ignore such irrelevant "table does
4998 not exist errors", we silently clear the error if TEMPORARY was used.
4999 */
5000 1149424 if (thd->lex->sql_command == SQLCOM_DROP_TABLE &&
5001
6/8
✓ Branch 0 taken 670 times.
✓ Branch 1 taken 13874 times.
✓ Branch 2 taken 670 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 669 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
14545 thd->lex->drop_temporary && thd->is_error() &&
5002
5/6
✓ Branch 0 taken 14544 times.
✓ Branch 1 taken 552896 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 567439 times.
581985 thd->get_stmt_da()->mysql_errno() == ER_BAD_TABLE_ERROR &&
5003 !expected_error) {
5004
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 thd->get_stmt_da()->reset_diagnostics_area();
5005 // Flag drops for error-ignored DDL to advance execution coordinates.
5006 1 has_ddl_committed = false;
5007 }
5008 /*
5009 If we expected a non-zero error code, and we don't get the same error
5010 code, and it should be ignored or is related to a concurrency issue.
5011 */
5012
3/4
✓ Branch 0 taken 567437 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 871 times.
✓ Branch 3 taken 566566 times.
567440 actual_error = thd->is_error() ? thd->get_stmt_da()->mysql_errno() : 0;
5013
3/8
✓ Branch 0 taken 567437 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 567440 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 567440 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
567437 DBUG_PRINT("info", ("expected_error: %d sql_errno: %d", expected_error,
5014 actual_error));
5015
5016
4/4
✓ Branch 0 taken 871 times.
✓ Branch 1 taken 566565 times.
✓ Branch 2 taken 234 times.
✓ Branch 3 taken 637 times.
567436 if (actual_error != 0 && expected_error == actual_error) {
5017 702 if (!has_ddl_committed && // Slave didn't commit a DDL
5018
1/2
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
234 ddl_xid == binary_log::INVALID_XID && // The event was not logged as
5019 // atomic DDL on master
5020
4/6
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 234 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 230 times.
702 !thd->rli_slave->ddl_not_atomic && // The DDL was considered atomic
5021 // by the slave
5022
3/4
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 230 times.
234 is_atomic_ddl(thd, true)) // The DDL is atomic for the local server
5023 {
5024
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 thd->get_stmt_da()->reset_diagnostics_area();
5025
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_SLAVE_POSSIBLY_DIVERGED_AFTER_DDL, MYF(0), 0);
5026 4 actual_error = ER_SLAVE_POSSIBLY_DIVERGED_AFTER_DDL;
5027 }
5028 }
5029
5030 /*
5031 If a statement with expected error is received on slave and if the
5032 statement is not filtered on the slave, only then compare the expected
5033 error with the actual error that happened on slave.
5034 */
5035
5/6
✓ Branch 0 taken 250 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 248 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 230 times.
250 if ((expected_error && rli->rpl_filter->db_ok(thd->db().str) &&
5036 18 expected_error != actual_error &&
5037
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
18 !concurrency_error_code(expected_error)) &&
5038
7/8
✓ Branch 0 taken 250 times.
✓ Branch 1 taken 567186 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 567424 times.
567698 !ignored_error_code(actual_error) &&
5039
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 !ignored_error_code(expected_error)) {
5040
3/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 3 times.
12 if (!ignored_error_code(ER_INCONSISTENT_ERROR)) {
5041
4/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
18 rli->report(
5042 ERROR_LEVEL, ER_INCONSISTENT_ERROR,
5043
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 ER_THD(thd, ER_INCONSISTENT_ERROR),
5044
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 ER_THD_NONCONST(thd, expected_error), expected_error,
5045 2 (actual_error ? thd->get_stmt_da()->message_text() : "no error"),
5046 actual_error, print_slave_db_safe(db), query_arg);
5047 9 thd->is_slave_error = true;
5048 } else {
5049
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 rli->report(
5050 INFORMATION_LEVEL, actual_error,
5051 "The actual error and expected error on slave are"
5052 " different that will result in ER_INCONSISTENT_ERROR but"
5053 " that is passed as an argument to replica_skip_errors so no"
5054 " error is thrown. "
5055 "The expected error was %s with, Error_code: %d. "
5056 "The actual error is %s with ",
5057
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ER_THD_NONCONST(thd, expected_error), expected_error,
5058 3 thd->get_stmt_da()->message_text());
5059
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
5060 }
5061 }
5062 /*
5063 If we get the same error code as expected and it is not a concurrency
5064 issue, or should be ignored.
5065 */
5066 1134207 else if ((expected_error == actual_error &&
5067
6/6
✓ Branch 0 taken 566783 times.
✓ Branch 1 taken 641 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 566779 times.
✓ Branch 4 taken 567126 times.
✓ Branch 5 taken 296 times.
568067 !concurrency_error_code(expected_error)) ||
5068
3/4
✓ Branch 0 taken 643 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 341 times.
✓ Branch 3 taken 302 times.
647 ignored_error_code(actual_error)) {
5069
3/8
✓ Branch 0 taken 567124 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 567126 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 567126 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
567126 DBUG_PRINT("info", ("error ignored"));
5070
7/8
✓ Branch 0 taken 571 times.
✓ Branch 1 taken 566555 times.
✓ Branch 2 taken 571 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 341 times.
✓ Branch 5 taken 230 times.
✓ Branch 6 taken 341 times.
✓ Branch 7 taken 566785 times.
567126 if (actual_error && ignored_error_code(actual_error)) {
5071
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 27 times.
341 if (actual_error == ER_SLAVE_IGNORED_TABLE) {
5072
3/4
✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 245 times.
314 if (!slave_ignored_err_throttle.log())
5073
2/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
69 rli->report(INFORMATION_LEVEL, actual_error,
5074 "Could not execute %s event. Detailed error: %s;"
5075 " Error log throttle is enabled. This error will not be"
5076 " displayed for next %lu secs. It will be suppressed",
5077 69 get_type_str(), thd->get_stmt_da()->message_text(),
5078 (window_size / 1000000));
5079 } else
5080
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
27 rli->report(INFORMATION_LEVEL, actual_error,
5081 "Could not execute %s event. Detailed error: %s;",
5082 27 get_type_str(), thd->get_stmt_da()->message_text());
5083 }
5084 567126 has_ddl_committed = false; // The same comments as above.
5085
1/2
✓ Branch 0 taken 567126 times.
✗ Branch 1 not taken.
567126 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
5086 567126 thd->killed = THD::NOT_KILLED;
5087 }
5088 /*
5089 Other cases: mostly we expected no error and get one.
5090 */
5091
4/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 290 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 296 times.
✗ Branch 5 not taken.
296 else if (thd->is_slave_error || thd->is_fatal_error()) {
5092
2/4
✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 296 times.
✗ Branch 3 not taken.
296 if (!is_silent_error(thd)) {
5093
2/4
✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 296 times.
✗ Branch 3 not taken.
592 rli->report(ERROR_LEVEL, actual_error,
5094 "Error '%s' on query. Default database: '%s'. Query: '%s'",
5095 296 (actual_error ? thd->get_stmt_da()->message_text()
5096 : "unexpected success or fatal error"),
5097
1/2
✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
296 print_slave_db_safe(thd->db().str), query_arg);
5098 }
5099 296 thd->is_slave_error = true;
5100 }
5101
5102 /*
5103 TODO: compare the values of "affected rows" around here. Something
5104 like:
5105 if ((uint32) affected_in_event != (uint32) affected_on_slave)
5106 {
5107 sql_print_error("Slave: did not get the expected number of affected "
5108 "rows running query from master - expected %d, got %d (this numbers "
5109 "should have matched modulo 4294967296).", 0, ...);
5110 thd->is_slave_error = 1;
5111 }
5112 We may also want an option to tell the slave to ignore "affected"
5113 mismatch. This mismatch could be implemented with a new ER_ code, and
5114 to ignore it you would use --replica-skip-errors...
5115
5116 To do the comparison we need to know the value of "affected" which the
5117 above dispatch_sql_command() computed. And we need to know the value of
5118 "affected" in the master's binlog. Both will be implemented later. The
5119 important thing is that we now have the format ready to log the values
5120 of "affected" in the binlog. So we can release 5.0.0 before effectively
5121 logging "affected" and effectively comparing it.
5122 */
5123
2/2
✓ Branch 0 taken 567440 times.
✓ Branch 1 taken 19 times.
567425 } /* End of if (db_ok(... */
5124
5125 {
5126 /**
5127 The following failure injection works in cooperation with tests
5128 setting @@global.debug= 'd,stop_replica_middle_group'.
5129 The sql thread receives the killed status and will proceed
5130 to shutdown trying to finish incomplete events group.
5131 */
5132
5133 // TODO: address the middle-group killing in MTS case
5134
5135
9/12
✓ Branch 0 taken 567439 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 567431 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
567440 DBUG_EXECUTE_IF("stop_replica_middle_group", {
5136 if (strcmp("COMMIT", query) != 0 && strcmp("BEGIN", query) != 0) {
5137 if (thd->get_transaction()->cannot_safely_rollback(
5138 Transaction_ctx::SESSION)) {
5139 auto thd_rli = (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL
5140 ? const_cast<Relay_log_info *>(rli)
5141 : static_cast<Slave_worker *>(
5142 const_cast<Relay_log_info *>(rli))
5143 ->c_rli);
5144 thd_rli->abort_slave = 1;
5145 }
5146 }
5147 };);
5148 }
5149
5150 567431 end:
5151
5152
3/4
✓ Branch 0 taken 3212 times.
✓ Branch 1 taken 564246 times.
✓ Branch 2 taken 3212 times.
✗ Branch 3 not taken.
567458 if (thd->temporary_tables) detach_temp_tables_worker(thd, rli);
5153 /*
5154 Probably we have set thd->query, thd->db, thd->catalog to point to places
5155 in the data_buf of this event. Now the event is going to be deleted
5156 probably, so data_buf will be freed, so the thd->... listed above will be
5157 pointers to freed memory.
5158 So we must set them to 0, so that those bad pointers values are not later
5159 used. Note that "cleanup" queries like automatic DROP TEMPORARY TABLE
5160 don't suffer from these assignments to 0 as DROP TEMPORARY
5161 TABLE uses the db.table syntax.
5162 */
5163 567458 thd->set_catalog(NULL_CSTR);
5164
1/2
✓ Branch 0 taken 567462 times.
✗ Branch 1 not taken.
567459 thd->set_db(NULL_CSTR); /* will free the current database */
5165
1/2
✓ Branch 0 taken 567462 times.
✗ Branch 1 not taken.
567462 thd->reset_query();
5166 567462 thd->lex->sql_command = SQLCOM_END;
5167
3/8
✓ Branch 0 taken 567461 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 567460 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 567460 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
567462 DBUG_PRINT("info", ("end: query= 0"));
5168
5169 /* Mark the statement completed. */
5170
1/2
✓ Branch 0 taken 567449 times.
✗ Branch 1 not taken.
567460 MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
5171
5172 /* Maintain compatibility with the legacy processlist. */
5173
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 567449 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
567449 if (pfs_processlist_enabled) thd->reset_query_for_display();
5174
5175
1/2
✓ Branch 0 taken 567454 times.
✗ Branch 1 not taken.
567449 thd->reset_rewritten_query();
5176 567454 thd->m_statement_psi = nullptr;
5177 567454 thd->m_digest = nullptr;
5178
5179 /*
5180 Prevent rewritten query from getting "stuck" in SHOW PROCESSLIST,
5181 and performance_schema.threads.
5182 */
5183
1/2
✓ Branch 0 taken 567457 times.
✗ Branch 1 not taken.
567454 thd->reset_rewritten_query();
5184
1/2
✓ Branch 0 taken 567461 times.
✗ Branch 1 not taken.
567457 thd->reset_query_for_display();
5185
5186 /*
5187 As a disk space optimization, future masters will not log an event for
5188 LAST_INSERT_ID() if that function returned 0 (and thus they will be able
5189 to replace the THD::stmt_depends_on_first_successful_insert_id_in_prev_stmt
5190 variable by (THD->first_successful_insert_id_in_prev_stmt > 0) ; with the
5191 resetting below we are ready to support that.
5192 */
5193 567461 thd->first_successful_insert_id_in_prev_stmt_for_binlog = 0;
5194 567461 thd->first_successful_insert_id_in_prev_stmt = 0;
5195 567461 thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt = false;
5196
1/2
✓ Branch 0 taken 567457 times.
✗ Branch 1 not taken.
567461 thd->mem_root->ClearForReuse();
5197 567460 return thd->is_slave_error;
5198 567457 }
5199
5200 985 int Query_log_event::do_update_pos(Relay_log_info *rli) {
5201 985 int ret = Log_event::do_update_pos(rli);
5202
5203
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 985 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
985 DBUG_EXECUTE_IF(
5204 "crash_after_commit_and_update_pos", if (!strcmp("COMMIT", query)) {
5205 sql_print_information("Crashing crash_after_commit_and_update_pos.");
5206 rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT);
5207 ha_flush_logs(0);
5208 DBUG_SUICIDE();
5209 });
5210
5211 985 return ret;
5212 }
5213
5214 568026 Log_event::enum_skip_reason Query_log_event::do_shall_skip(
5215 Relay_log_info *rli) {
5216
1/2
✓ Branch 0 taken 568026 times.
✗ Branch 1 not taken.
568026 DBUG_TRACE;
5217
3/8
✓ Branch 0 taken 568026 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 568026 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 568026 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
568026 DBUG_PRINT("debug", ("query: %s; q_len: %d", query, static_cast<int>(q_len)));
5218
2/4
✓ Branch 0 taken 568026 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 568026 times.
✗ Branch 3 not taken.
568026 assert(query && q_len > 0);
5219
5220
2/2
✓ Branch 0 taken 438 times.
✓ Branch 1 taken 567588 times.
568026 if (rli->slave_skip_counter > 0) {
5221
2/2
✓ Branch 0 taken 341 times.
✓ Branch 1 taken 97 times.
438 if (strcmp("BEGIN", query) == 0) {
5222 341 thd->variables.option_bits |= OPTION_BEGIN;
5223
1/2
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
341 return Log_event::continue_group(rli);
5224 }
5225
5226
3/4
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
97 if (strcmp("COMMIT", query) == 0 || strcmp("ROLLBACK", query) == 0) {
5227 27 thd->variables.option_bits &= ~OPTION_BEGIN;
5228 27 return Log_event::EVENT_SKIP_COUNT;
5229 }
5230 }
5231
1/2
✓ Branch 0 taken 567658 times.
✗ Branch 1 not taken.
567658 Log_event::enum_skip_reason ret = Log_event::do_shall_skip(rli);
5232 567658 return ret;
5233 568026 }
5234
5235 #endif
5236
5237 /**
5238 Return the query string pointer (and its size) from a Query log event
5239 using only the event buffer (we don't instantiate a Query_log_event
5240 object for this).
5241
5242 @param buf Pointer to the event buffer.
5243 @param length The size of the event buffer.
5244 @param fd_event The description event of the master which logged
5245 the event.
5246 @param[out] query_arg The pointer to receive the query pointer.
5247
5248 @return The size of the query.
5249 */
5250 573711 size_t Query_log_event::get_query(const char *buf, size_t length,
5251 const Format_description_event *fd_event,
5252 const char **query_arg) {
5253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 573711 times.
573711 assert((Log_event_type)buf[EVENT_TYPE_OFFSET] == binary_log::QUERY_EVENT);
5254
5255 char db_len; /* size of db name */
5256 573711 uint status_vars_len = 0; /* size of status_vars */
5257 size_t qlen; /* size of the query */
5258 573711 int checksum_size = 0; /* size of trailing checksum */
5259 const char *end_of_query;
5260
5261 573711 uint common_header_len = fd_event->common_header_len;
5262 uint query_header_len =
5263 573711 fd_event->post_header_len[binary_log::QUERY_EVENT - 1];
5264
5265 /* Error if the event content is too small */
5266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 573711 times.
573711 if (length < (common_header_len + query_header_len)) goto err;
5267
5268 /* Skip the header */
5269 573711 buf += common_header_len;
5270
5271 /* Check if there are status variables in the event */
5272
1/2
✓ Branch 0 taken 573711 times.
✗ Branch 1 not taken.
573711 if ((query_header_len - QUERY_HEADER_MINIMAL_LEN) > 0) {
5273 573711 status_vars_len = uint2korr(buf + Q_STATUS_VARS_LEN_OFFSET);
5274 }
5275
5276 /* Check if the event has trailing checksum */
5277
2/2
✓ Branch 0 taken 549283 times.
✓ Branch 1 taken 24428 times.
573711 if (fd_event->footer()->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF)
5278 549283 checksum_size = 4;
5279
5280 573711 db_len = (uchar)buf[Q_DB_LEN_OFFSET];
5281
5282 /* Error if the event content is too small */
5283 573711 if (length < (common_header_len + query_header_len + db_len + 1 +
5284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 573711 times.
573711 status_vars_len + checksum_size))
5285 goto err;
5286
5287 573711 *query_arg = buf + query_header_len + db_len + 1 + status_vars_len;
5288
5289 /* Calculate the query length */
5290 573711 end_of_query = buf +
5291 573711 (length - common_header_len) - /* we skipped the header */
5292 573711 checksum_size;
5293 573711 qlen = end_of_query - *query_arg;
5294 573711 return qlen;
5295
5296 err:
5297 *query_arg = nullptr;
5298 return 0;
5299 }
5300
5301 /***************************************************************************
5302 Format_description_log_event methods
5303 ****************************************************************************/
5304
5305 /**
5306 Format_description_log_event 1st ctor.
5307
5308 Ctor. Can be used to create the event to write to the binary log (when the
5309 server starts or when FLUSH LOGS).
5310 */
5311 171925 Format_description_log_event::Format_description_log_event()
5312 : Format_description_event(BINLOG_VERSION, ::server_version),
5313 #ifdef MYSQL_SERVER
5314 Log_event(header(), footer(), Log_event::EVENT_INVALID_CACHE,
5315
1/2
✓ Branch 0 taken 171915 times.
✗ Branch 1 not taken.
171925 Log_event::EVENT_INVALID_LOGGING)
5316 #else
5317 Log_event(header(), footer())
5318 #endif
5319 {
5320 171918 common_header->set_is_valid(true);
5321 171925 }
5322
5323 /**
5324 The problem with this constructor is that the fixed header may have a
5325 length different from this version, but we don't know this length as we
5326 have not read the Format_description_log_event which says it, yet. This
5327 length is in the post-header of the event, but we don't know where the
5328 post-header starts.
5329
5330 So this type of event HAS to:
5331 - either have the header's length at the beginning (in the header, at a
5332 fixed position which will never be changed), not in the post-header. That
5333 would make the header be "shifted" compared to other events.
5334 - or have a header of size LOG_EVENT_MINIMAL_HEADER_LEN (19), in all future
5335 versions, so that we know for sure.
5336
5337 I (Guilhem) chose the 2nd solution. Rotate has the same constraint (because
5338 it is sent before Format_description_log_event).
5339 */
5340
5341 167936 Format_description_log_event::Format_description_log_event(
5342 167936 const char *buf, const Format_description_event *description_event)
5343 : Format_description_event(buf, description_event),
5344
1/2
✓ Branch 0 taken 163328 times.
✗ Branch 1 not taken.
167936 Log_event(header(), footer()) {
5345
1/2
✓ Branch 0 taken 167938 times.
✗ Branch 1 not taken.
167933 DBUG_TRACE;
5346
3/4
✓ Branch 0 taken 163327 times.
✓ Branch 1 taken 4606 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 163327 times.
167938 if (!is_valid()) return;
5347 167933 common_header->type_code = binary_log::FORMAT_DESCRIPTION_EVENT;
5348
1/2
✓ Branch 0 taken 167938 times.
✗ Branch 1 not taken.
167933 }
5349
5350 #ifndef MYSQL_SERVER
5351 4580 void Format_description_log_event::print(
5352 FILE *, PRINT_EVENT_INFO *print_event_info) const {
5353
1/2
✓ Branch 0 taken 4580 times.
✗ Branch 1 not taken.
4580 DBUG_TRACE;
5354
5355 4580 IO_CACHE *const head = &print_event_info->head_cache;
5356
5357
2/2
✓ Branch 0 taken 4322 times.
✓ Branch 1 taken 258 times.
4580 if (!print_event_info->short_form) {
5358
1/2
✓ Branch 0 taken 4322 times.
✗ Branch 1 not taken.
4322 print_header(head, print_event_info, false);
5359 4322 my_b_printf(head, "\tStart: binlog v %d, server v %s created ",
5360
1/2
✓ Branch 0 taken 4322 times.
✗ Branch 1 not taken.
4322 binlog_version, server_version);
5361
1/2
✓ Branch 0 taken 4322 times.
✗ Branch 1 not taken.
4322 print_timestamp(head, nullptr);
5362
3/4
✓ Branch 0 taken 3715 times.
✓ Branch 1 taken 607 times.
✓ Branch 2 taken 3715 times.
✗ Branch 3 not taken.
4322 if (created) my_b_printf(head, " at startup");
5363
1/2
✓ Branch 0 taken 4322 times.
✗ Branch 1 not taken.
4322 my_b_printf(head, "\n");
5364
2/2
✓ Branch 0 taken 3683 times.
✓ Branch 1 taken 639 times.
4322 if (common_header->flags & LOG_EVENT_BINLOG_IN_USE_F)
5365
1/2
✓ Branch 0 taken 3683 times.
✗ Branch 1 not taken.
3683 my_b_printf(head,
5366 "# Warning: this binlog is either in use or was not "
5367 "closed properly.\n");
5368 }
5369
5370
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 4548 times.
4580 if (is_relay_log_event()) {
5371
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 my_b_printf(head,
5372 "# This Format_description_event appears in a relay log "
5373 "and was generated by the slave thread.\n");
5374 32 return;
5375 }
5376
5377
6/6
✓ Branch 0 taken 4534 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 3848 times.
✓ Branch 3 taken 686 times.
✓ Branch 4 taken 3848 times.
✓ Branch 5 taken 700 times.
4548 if (!is_artificial_event() && created) {
5378 #ifdef WHEN_WE_HAVE_THE_RESET_CONNECTION_SQL_COMMAND
5379 /*
5380 This is for mysqlbinlog: like in replication, we want to delete the stale
5381 tmp files left by an unclean shutdown of mysqld (temporary tables)
5382 and rollback unfinished transaction.
5383 Probably this can be done with RESET CONNECTION (syntax to be defined).
5384 */
5385 my_b_printf(head, "RESET CONNECTION%s\n", print_event_info->delimiter);
5386 #else
5387
1/2
✓ Branch 0 taken 3848 times.
✗ Branch 1 not taken.
3848 my_b_printf(head, "ROLLBACK%s\n", print_event_info->delimiter);
5388 #endif
5389 }
5390
3/4
✓ Branch 0 taken 4548 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4520 times.
✓ Branch 3 taken 28 times.
4548 if (temp_buf && print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER &&
5391
2/2
✓ Branch 0 taken 4286 times.
✓ Branch 1 taken 234 times.
4520 !print_event_info->short_form) {
5392
2/2
✓ Branch 0 taken 4243 times.
✓ Branch 1 taken 43 times.
4286 if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
5393
1/2
✓ Branch 0 taken 4243 times.
✗ Branch 1 not taken.
4243 my_b_printf(head, "BINLOG '\n");
5394
1/2
✓ Branch 0 taken 4286 times.
✗ Branch 1 not taken.
4286 print_base64(head, print_event_info, false);
5395 4286 print_event_info->printed_fd_event = true;
5396
5397 /*
5398 If --skip-gtids is given, the server when it replays the output
5399 should generate a new GTID if gtid_mode=ON. However, when the
5400 server reads the base64-encoded Format_description_log_event, it
5401 will cleverly detect that this is a binlog to be replayed, and
5402 act a little bit like the replication thread, in the following
5403 sense: if the thread does not see any 'SET GTID_NEXT' statement,
5404 it will assume the binlog was created by an old server and try
5405 to preserve transactions as anonymous. This is the opposite of
5406 what we want when passing the --skip-gtids flag, so therefore we
5407 output the following statement.
5408
5409 The behavior where the client preserves transactions following a
5410 Format_description_log_event as anonymous was introduced in
5411 5.6.16.
5412 */
5413
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4283 times.
4286 if (print_event_info->skip_gtids)
5414 3 my_b_printf(head, "/*!50616 SET @@SESSION.GTID_NEXT='AUTOMATIC'*/%s\n",
5415
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 print_event_info->delimiter);
5416 }
5417
2/2
✓ Branch 0 taken 4548 times.
✓ Branch 1 taken 32 times.
4580 }
5418 #endif /* !MYSQL_SERVER */
5419
5420 #ifdef MYSQL_SERVER
5421 4752 int Format_description_log_event::pack_info(Protocol *protocol) {
5422 char buf[12 + ST_SERVER_VER_LEN + 14 + 22], *pos;
5423 4752 pos = my_stpcpy(buf, "Server ver: ");
5424 4752 pos = my_stpcpy(pos, server_version);
5425 4752 pos = my_stpcpy(pos, ", Binlog ver: ");
5426
1/2
✓ Branch 0 taken 4752 times.
✗ Branch 1 not taken.
4752 pos = longlong10_to_str(binlog_version, pos, 10);
5427
1/2
✓ Branch 0 taken 4752 times.
✗ Branch 1 not taken.
4752 protocol->store_string(buf, (uint)(pos - buf), &my_charset_bin);
5428 4752 return 0;
5429 }
5430
5431 89990 bool Format_description_log_event::write(Basic_ostream *ostream) {
5432 bool ret;
5433 bool no_checksum;
5434 uchar buff[Binary_log_event::FORMAT_DESCRIPTION_HEADER_LEN +
5435 BINLOG_CHECKSUM_ALG_DESC_LEN];
5436 89990 size_t rec_size = sizeof(buff);
5437 89990 int2store(buff + ST_BINLOG_VER_OFFSET, binlog_version);
5438 89990 memcpy((char *)buff + ST_SERVER_VER_OFFSET, server_version,
5439 ST_SERVER_VER_LEN);
5440
3/4
✓ Branch 0 taken 43385 times.
✓ Branch 1 taken 46605 times.
✓ Branch 2 taken 43385 times.
✗ Branch 3 not taken.
89990 if (!dont_set_created) created = get_time();
5441 89990 int4store(buff + ST_CREATED_OFFSET, static_cast<uint32>(created));
5442 89990 buff[ST_COMMON_HEADER_LEN_OFFSET] = LOG_EVENT_HEADER_LEN;
5443
5444 89990 size_t number_of_events = 0;
5445 89990 int post_header_len_size = static_cast<int>(post_header_len.size());
5446
5447
1/2
✓ Branch 0 taken 89990 times.
✗ Branch 1 not taken.
89990 if (post_header_len_size == Binary_log_event::LOG_EVENT_TYPES)
5448 // Replicating between master and slave with same version.
5449 // number_of_events will be same as Binary_log_event::LOG_EVENT_TYPES
5450 89990 number_of_events = Binary_log_event::LOG_EVENT_TYPES;
5451 else if (post_header_len_size > Binary_log_event::LOG_EVENT_TYPES)
5452 /*
5453 Replicating between new master and old slave.
5454 In that case there won't be any memory issues, as there won't be
5455 any out of memory read.
5456 */
5457 number_of_events = Binary_log_event::LOG_EVENT_TYPES;
5458 else
5459 /*
5460 Replicating between old master and new slave.
5461 In that case it might lead to different number_of_events on master and
5462 slave. When the relay log is rotated, the FDE from master is used to
5463 create the FDE event on slave, which is being written here. In that case
5464 we might end up reading more bytes as
5465 post_header_len.size() < Binary_log_event::LOG_EVENT_TYPES;
5466 causing memory issues.
5467 */
5468 number_of_events = post_header_len_size;
5469
5470 89990 memcpy((char *)buff + ST_COMMON_HEADER_LEN_OFFSET + 1,
5471 89990 &post_header_len.front(), number_of_events);
5472 /*
5473 if checksum is requested
5474 record the checksum-algorithm descriptor next to
5475 post_header_len vector which will be followed by the checksum value.
5476 Master is supposed to trigger checksum computing by binlog_checksum_options,
5477 slave does it via marking the event according to
5478 FD_queue checksum_alg value.
5479 */
5480 static_assert(BINLOG_CHECKSUM_ALG_DESC_LEN == 1, "");
5481 #ifndef NDEBUG
5482 89990 common_header->data_written = 0; // to prepare for need_checksum assert
5483 #endif
5484 89990 buff[Binary_log_event::FORMAT_DESCRIPTION_HEADER_LEN] =
5485
3/4
✓ Branch 0 taken 89990 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 78915 times.
✓ Branch 3 taken 11075 times.
89990 need_checksum() ? (uint8)common_footer->checksum_alg
5486 : (uint8)binary_log::BINLOG_CHECKSUM_ALG_OFF;
5487 /*
5488 FD of checksum-aware server is always checksum-equipped, (V) is in,
5489 regardless of @@global.binlog_checksum policy.
5490 Thereby a combination of (A) == 0, (V) != 0 means
5491 it's the checksum-aware server's FD event that heads checksum-free binlog
5492 file.
5493 Here 0 stands for checksumming OFF to evaluate (V) as 0 is that case.
5494 A combination of (A) != 0, (V) != 0 denotes FD of the checksum-aware server
5495 heading the checksummed binlog.
5496 (A), (V) presence in FD of the checksum-aware server makes the event
5497 1 + 4 bytes bigger comparing to the former FD.
5498 */
5499
5500
2/2
✓ Branch 0 taken 11075 times.
✓ Branch 1 taken 78915 times.
89990 if ((no_checksum = (common_footer->checksum_alg ==
5501 binary_log::BINLOG_CHECKSUM_ALG_OFF))) {
5502 // Forcing (V) room to fill anyway
5503 11075 common_footer->checksum_alg = binary_log::BINLOG_CHECKSUM_ALG_CRC32;
5504 }
5505
1/2
✓ Branch 0 taken 89990 times.
✗ Branch 1 not taken.
89990 ret = (write_header(ostream, rec_size) ||
5506
3/6
✓ Branch 0 taken 89990 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 89990 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 89990 times.
✗ Branch 5 not taken.
179980 wrapper_my_b_safe_write(ostream, buff, rec_size) ||
5507
2/4
✓ Branch 0 taken 89990 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 89990 times.
89990 write_footer(ostream));
5508
2/2
✓ Branch 0 taken 11075 times.
✓ Branch 1 taken 78915 times.
89990 if (no_checksum)
5509 11075 common_footer->checksum_alg = binary_log::BINLOG_CHECKSUM_ALG_OFF;
5510 89990 return ret;
5511 }
5512
5513 49924 int Format_description_log_event::do_apply_event(Relay_log_info const *rli) {
5514 49924 int ret = 0;
5515
1/2
✓ Branch 0 taken 49924 times.
✗ Branch 1 not taken.
49924 DBUG_TRACE;
5516
5517 /*
5518 As a transaction NEVER spans on 2 or more binlogs:
5519 if we have an active transaction at this point, the master died
5520 while writing the transaction to the binary log, i.e. while
5521 flushing the binlog cache to the binlog. XA guarantees that master has
5522 rolled back. So we roll back.
5523 Note: this event could be sent by the master to inform us of the
5524 format of its binlog; in other words maybe it is not at its
5525 original place when it comes to us; we'll know this by checking
5526 log_pos ("artificial" events have log_pos == 0).
5527 */
5528
8/10
✓ Branch 0 taken 49228 times.
✓ Branch 1 taken 696 times.
✓ Branch 2 taken 44895 times.
✓ Branch 3 taken 4333 times.
✓ Branch 4 taken 11521 times.
✓ Branch 5 taken 33374 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11521 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 49924 times.
61445 if (!thd->rli_fake && !is_artificial_event() && created &&
5529 11521 thd->get_transaction()->is_active(Transaction_ctx::SESSION)) {
5530 /* This is not an error (XA is safe), just an information */
5531 rli->report(INFORMATION_LEVEL, 0,
5532 "Rolling back unfinished transaction (no COMMIT "
5533 "or ROLLBACK in relay log). A probable cause is that "
5534 "the master died while writing the transaction to "
5535 "its binary log, thus rolled back too.");
5536 const_cast<Relay_log_info *>(rli)->cleanup_context(thd, true);
5537 }
5538
5539 /* If this event comes from ourself, there is no cleaning task to perform. */
5540
2/2
✓ Branch 0 taken 14028 times.
✓ Branch 1 taken 35896 times.
49924 if (server_id != (uint32)::server_id) {
5541
4/4
✓ Branch 0 taken 4952 times.
✓ Branch 1 taken 9076 times.
✓ Branch 2 taken 4077 times.
✓ Branch 3 taken 875 times.
14028 if (created && !thd->variables.require_row_format) {
5542
1/2
✓ Branch 0 taken 4077 times.
✗ Branch 1 not taken.
4077 ret = close_temporary_tables(thd);
5543
1/2
✓ Branch 0 taken 4077 times.
✗ Branch 1 not taken.
4077 cleanup_load_tmpdir();
5544 } else {
5545 /*
5546 Set all temporary tables thread references to the current thread
5547 as they may point to the "old" SQL slave thread in case of its
5548 restart.
5549 */
5550 TABLE *table;
5551
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 9951 times.
10048 for (table = thd->temporary_tables; table; table = table->next)
5552 97 table->in_use = thd;
5553 }
5554 }
5555
5556
1/2
✓ Branch 0 taken 49924 times.
✗ Branch 1 not taken.
49924 if (!ret) {
5557 /* Save the information describing this binlog */
5558
1/2
✓ Branch 0 taken 49924 times.
✗ Branch 1 not taken.
49924 ret = const_cast<Relay_log_info *>(rli)->set_rli_description_event(this);
5559 }
5560
5561 49924 return ret;
5562 49924 }
5563
5564 49228 int Format_description_log_event::do_update_pos(Relay_log_info *rli) {
5565
2/2
✓ Branch 0 taken 35736 times.
✓ Branch 1 taken 13492 times.
49228 if (server_id == (uint32)::server_id) {
5566 /*
5567 We only increase the relay log position if we are skipping
5568 events and do not touch any group_* variables, nor flush the
5569 relay log info. If there is a crash, we will have to re-skip
5570 the events again, but that is a minor issue.
5571
5572 If we do not skip stepping the group log position (and the
5573 server id was changed when restarting the server), it might well
5574 be that we start executing at a position that is invalid, e.g.,
5575 at a Rows_log_event or a Query_log_event preceded by a
5576 Intvar_log_event instead of starting at a Table_map_log_event or
5577 the Intvar_log_event respectively.
5578 */
5579 35736 rli->inc_event_relay_log_pos();
5580 35736 return 0;
5581 } else {
5582 13492 return Log_event::do_update_pos(rli);
5583 }
5584 }
5585
5586 49210 Log_event::enum_skip_reason Format_description_log_event::do_shall_skip(
5587 Relay_log_info *) {
5588 49210 return Log_event::EVENT_SKIP_NOT;
5589 }
5590
5591 #endif /* MYSQL_SERVER */
5592
5593 29 Start_encryption_log_event::Start_encryption_log_event(
5594 29 const char *buf, const Format_description_event *description_event)
5595 : Start_encryption_event(buf, description_event),
5596
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
29 Log_event(header(), footer()) {}
5597
5598 #ifdef MYSQL_SERVER
5599 2 int Start_encryption_log_event::do_update_pos(Relay_log_info *rli) {
5600 /*
5601 Master never sends Start_encryption_log_event, any SELE that a slave
5602 might see was created locally in MYSQL_BIN_LOG::open() on the slave
5603 */
5604 2 rli->inc_event_relay_log_pos();
5605 2 return 0;
5606 }
5607
5608 #endif
5609
5610 #ifndef MYSQL_SERVER
5611 6 void Start_encryption_log_event::print(
5612 FILE *file [[maybe_unused]],
5613 PRINT_EVENT_INFO *print_event_info) const {
5614 // Need 2 characters per one hex + 2 for 0x + 1 for \0
5615 char nonce_buf[NONCE_LENGTH * 2 + 2 + 1];
5616
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 str_to_hex(nonce_buf, reinterpret_cast<const char *>(nonce), NONCE_LENGTH);
5617
5618 6 IO_CACHE *const head = &print_event_info->head_cache;
5619
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 print_header(head, print_event_info, false);
5620
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_b_printf(head, "Encryption scheme: %d", crypto_scheme);
5621
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_b_printf(head, ", key_version: %d", key_version);
5622
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_b_printf(head, ", nonce: %s ", nonce_buf);
5623
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_b_printf(head,
5624 "\n# The rest of the binlog is encrypted with Percona Server 5.7 "
5625 "encryption!\n");
5626 6 }
5627 #endif
5628
5629 /**************************************************************************
5630 Rotate_log_event methods
5631 **************************************************************************/
5632
5633 #ifdef MYSQL_SERVER
5634
5635 /*
5636 Rotate_log_event::pack_info()
5637 */
5638
5639 1730 int Rotate_log_event::pack_info(Protocol *protocol) {
5640 char buf1[256], buf[22];
5641 1730 String tmp(buf1, sizeof(buf1), log_cs);
5642 1730 tmp.length(0);
5643
1/2
✓ Branch 0 taken 1730 times.
✗ Branch 1 not taken.
1730 tmp.append(new_log_ident, ident_len);
5644
1/2
✓ Branch 0 taken 1730 times.
✗ Branch 1 not taken.
1730 tmp.append(STRING_WITH_LEN(";pos="));
5645
2/4
✓ Branch 0 taken 1730 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1730 times.
✗ Branch 3 not taken.
1730 tmp.append(llstr(pos, buf));
5646
1/2
✓ Branch 0 taken 1730 times.
✗ Branch 1 not taken.
1730 protocol->store_string(tmp.ptr(), tmp.length(), &my_charset_bin);
5647 1730 return 0;
5648 1730 }
5649 #endif // MYSQL_SERVER
5650
5651 /*
5652 Rotate_log_event::print()
5653 */
5654
5655 #ifndef MYSQL_SERVER
5656 726 void Rotate_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
5657 char buf[22];
5658 726 IO_CACHE *const head = &print_event_info->head_cache;
5659
5660
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 534 times.
726 if (print_event_info->short_form) return;
5661
1/2
✓ Branch 0 taken 534 times.
✗ Branch 1 not taken.
534 print_header(head, print_event_info, false);
5662
1/2
✓ Branch 0 taken 534 times.
✗ Branch 1 not taken.
534 my_b_printf(head, "\tRotate to ");
5663
1/2
✓ Branch 0 taken 534 times.
✗ Branch 1 not taken.
534 if (new_log_ident) {
5664 [[maybe_unused]]
5665
1/2
✓ Branch 0 taken 534 times.
✗ Branch 1 not taken.
534 int write_res = my_b_write(head, pointer_cast<const uchar *>(new_log_ident),
5666 534 (uint)ident_len);
5667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 534 times.
534 assert(write_res == 0);
5668 }
5669
2/4
✓ Branch 0 taken 534 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 534 times.
✗ Branch 3 not taken.
534 my_b_printf(head, " pos: %s\n", llstr(pos, buf));
5670 }
5671 #endif /* !MYSQL_SERVER */
5672
5673 /*
5674 Rotate_log_event::Rotate_log_event() (2 constructors)
5675 */
5676
5677 #ifdef MYSQL_SERVER
5678 47127 Rotate_log_event::Rotate_log_event(const char *new_log_ident_arg,
5679 size_t ident_len_arg, ulonglong pos_arg,
5680 47127 uint flags_arg)
5681 : binary_log::Rotate_event(new_log_ident_arg, ident_len_arg, flags_arg,
5682 pos_arg),
5683 Log_event(header(), footer(), Log_event::EVENT_NO_CACHE,
5684
1/2
✓ Branch 0 taken 47127 times.
✗ Branch 1 not taken.
47127 Log_event::EVENT_IMMEDIATE_LOGGING) {
5685 #ifndef NDEBUG
5686
1/2
✓ Branch 0 taken 47127 times.
✗ Branch 1 not taken.
47127 DBUG_TRACE;
5687 #endif
5688 47127 new_log_ident = new_log_ident_arg;
5689 47127 pos = pos_arg;
5690
1/2
✓ Branch 0 taken 47127 times.
✗ Branch 1 not taken.
47127 ident_len = ident_len_arg ? ident_len_arg : (uint)strlen(new_log_ident_arg);
5691 47127 flags = flags_arg;
5692
5693 #ifndef NDEBUG
5694 char buff[22];
5695
3/10
✓ Branch 0 taken 47127 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47127 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 47127 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
47127 DBUG_PRINT("enter", ("new_log_ident: %s pos: %s flags: %lu",
5696 new_log_ident_arg, llstr(pos_arg, buff), (ulong)flags));
5697 #endif
5698
2/2
✓ Branch 0 taken 13169 times.
✓ Branch 1 taken 33958 times.
47127 if (flags & DUP_NAME)
5699
1/2
✓ Branch 0 taken 13169 times.
✗ Branch 1 not taken.
13169 new_log_ident = my_strndup(key_memory_log_event, new_log_ident_arg,
5700 ident_len, MYF(MY_WME));
5701 47127 common_header->set_is_valid(new_log_ident != nullptr);
5702
2/2
✓ Branch 0 taken 24264 times.
✓ Branch 1 taken 22863 times.
47127 if (flags & RELAY_LOG) set_relay_log_event();
5703 47127 }
5704 #endif // MYSQL_SERVER
5705
5706 83646 Rotate_log_event::Rotate_log_event(
5707 83646 const char *buf, const Format_description_event *description_event)
5708 : binary_log::Rotate_event(buf, description_event),
5709
1/2
✓ Branch 0 taken 82631 times.
✗ Branch 1 not taken.
83646 Log_event(header(), footer()) {
5710
1/2
✓ Branch 0 taken 83646 times.
✗ Branch 1 not taken.
83646 DBUG_TRACE;
5711
3/4
✓ Branch 0 taken 82630 times.
✓ Branch 1 taken 1015 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 82630 times.
83646 if (!is_valid()) return;
5712
3/8
✓ Branch 0 taken 83646 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83646 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 83646 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
83645 DBUG_PRINT("debug", ("new_log_ident: '%s'", new_log_ident));
5713
1/2
✓ Branch 0 taken 83646 times.
✗ Branch 1 not taken.
83646 }
5714
5715 /*
5716 Rotate_log_event::write()
5717 */
5718
5719 #ifdef MYSQL_SERVER
5720 46028 bool Rotate_log_event::write(Basic_ostream *ostream) {
5721 char buf[Binary_log_event::ROTATE_HEADER_LEN];
5722 46028 int8store(buf + R_POS_OFFSET, pos);
5723 return (
5724
1/2
✓ Branch 0 taken 46028 times.
✗ Branch 1 not taken.
46028 write_header(ostream, Binary_log_event::ROTATE_HEADER_LEN + ident_len) ||
5725
2/4
✓ Branch 0 taken 46028 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46028 times.
✗ Branch 3 not taken.
46028 wrapper_my_b_safe_write(ostream, (uchar *)buf,
5726 46028 Binary_log_event::ROTATE_HEADER_LEN) ||
5727
2/4
✓ Branch 0 taken 46028 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46028 times.
✗ Branch 3 not taken.
46027 wrapper_my_b_safe_write(ostream,
5728 46028 pointer_cast<const uchar *>(new_log_ident),
5729
1/2
✓ Branch 0 taken 46028 times.
✗ Branch 1 not taken.
138084 (uint)ident_len) ||
5730
2/4
✓ Branch 0 taken 46028 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 46028 times.
92056 write_footer(ostream));
5731 }
5732
5733 /*
5734 Got a rotate log event from the master.
5735
5736 This is mainly used so that we can later figure out the logname and
5737 position for the master.
5738
5739 We can't rotate the slave's BINlog as this will cause infinitive rotations
5740 in a A -> B -> A setup.
5741 The NOTES below is a wrong comment which will disappear when 4.1 is merged.
5742
5743 This must only be called from the Slave SQL thread, since it calls
5744 flush_relay_log_info().
5745
5746 @retval
5747 0 ok
5748 */
5749 54538 int Rotate_log_event::do_update_pos(Relay_log_info *rli) {
5750 54538 int error = 0;
5751
1/2
✓ Branch 0 taken 54538 times.
✗ Branch 1 not taken.
54538 DBUG_TRACE;
5752 #ifndef NDEBUG
5753 char buf[32];
5754 #endif
5755
5756
3/8
✓ Branch 0 taken 54538 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54538 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 54538 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
54538 DBUG_PRINT("info", ("server_id=%lu; ::server_id=%lu", (ulong)this->server_id,
5757 (ulong)::server_id));
5758
3/8
✓ Branch 0 taken 54538 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54538 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 54538 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
54538 DBUG_PRINT("info", ("new_log_ident: %s", this->new_log_ident));
5759
3/10
✓ Branch 0 taken 54538 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54538 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 54538 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
54538 DBUG_PRINT("info", ("pos: %s", llstr(this->pos, buf)));
5760
5761
10/16
✓ Branch 0 taken 54538 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 54536 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
54539 DBUG_EXECUTE_IF("block_on_master_pos_4_rotate", {
5762 if (server_id == 1 && pos == 4) {
5763 std::string action =
5764 "now signal signal.reach_pos_4_rotate_event wait_for "
5765 "signal.rotate_event_continue";
5766 assert(
5767 !debug_sync_set_action(current_thd, action.c_str(), action.size()));
5768 }
5769 });
5770
5771 /*
5772 If we are in a transaction or in a group: the only normal case is
5773 when the I/O thread was copying a big transaction, then it was
5774 stopped and restarted: we have this in the relay log:
5775
5776 BEGIN
5777 ...
5778 ROTATE (a fake one)
5779 ...
5780 COMMIT or ROLLBACK
5781
5782 In that case, we don't want to touch the coordinates which
5783 correspond to the beginning of the transaction. Starting from
5784 5.0.0, there also are some rotates from the slave itself, in the
5785 relay log, which shall not change the group positions.
5786 */
5787
5788 /*
5789 The way we check if SQL thread is currently in a group is different
5790 for STS and MTS.
5791 */
5792
1/2
✓ Branch 0 taken 54538 times.
✗ Branch 1 not taken.
54538 bool in_group = rli->is_parallel_exec()
5793
2/2
✓ Branch 0 taken 54412 times.
✓ Branch 1 taken 126 times.
54538 ? (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP)
5794
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 : rli->is_in_group();
5795
5796
2/2
✓ Branch 0 taken 5056 times.
✓ Branch 1 taken 18023 times.
23079 if ((server_id != ::server_id || rli->replicate_same_server_id) &&
5797
8/8
✓ Branch 0 taken 23079 times.
✓ Branch 1 taken 31459 times.
✓ Branch 2 taken 31462 times.
✓ Branch 3 taken 5053 times.
✓ Branch 4 taken 31322 times.
✓ Branch 5 taken 140 times.
✓ Branch 6 taken 31322 times.
✓ Branch 7 taken 23216 times.
77617 !is_relay_log_event() && !in_group) {
5798
5/6
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31158 times.
✓ Branch 3 taken 164 times.
✓ Branch 4 taken 31158 times.
✓ Branch 5 taken 164 times.
62480 if (!is_mts_db_partitioned(rli) &&
5799
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 31154 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
31158 (server_id != ::server_id || rli->replicate_same_server_id)) {
5800 // force the coordinator to start a new binlog segment.
5801 31158 static_cast<Mts_submode_logical_clock *>(rli->current_mts_submode)
5802 31158 ->start_new_group();
5803 }
5804
3/4
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31252 times.
✓ Branch 3 taken 70 times.
31322 if (rli->is_parallel_exec()) {
5805 /*
5806 Rotate events are special events that are handled as a
5807 synchronization point. For that reason, the checkpoint
5808 routine is being called here.
5809 */
5810
2/4
✓ Branch 0 taken 31252 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 31252 times.
31252 if ((error = mta_checkpoint_routine(rli, false))) goto err;
5811 }
5812
5813
1/2
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
31322 mysql_mutex_lock(&rli->data_lock);
5814
3/8
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31322 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 31322 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
31322 DBUG_PRINT("info", ("old group_master_log_name: '%s' "
5815 "old group_master_log_pos: %lu",
5816 rli->get_group_master_log_name(),
5817 (ulong)rli->get_group_master_log_pos()));
5818
5819 62644 memcpy(const_cast<char *>(rli->get_group_master_log_name()), new_log_ident,
5820 31322 ident_len + 1);
5821
1/2
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
31322 rli->notify_group_master_log_name_update();
5822 /*
5823 Execution coordinate update by Rotate itself needs forced flush
5824 otherwise in crash case MTS won't be able to find the starting point
5825 for recovery.
5826 It is safe to update the last executed coordinates because all Worker
5827 assignments prior to Rotate has been already processed (as well as
5828 above call to @c mta_checkpoint_routine has harvested their
5829 contribution to the last executed coordinates).
5830 */
5831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31322 times.
31322 if ((error = rli->inc_group_relay_log_pos(
5832
1/2
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
31322 pos, false /* need_data_lock=false */, true /* force flush */))) {
5833 mysql_mutex_unlock(&rli->data_lock);
5834 goto err;
5835 }
5836
5837
3/8
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31322 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 31322 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
31322 DBUG_PRINT("info", ("new group_master_log_name: '%s' "
5838 "new group_master_log_pos: %lu",
5839 rli->get_group_master_log_name(),
5840 (ulong)rli->get_group_master_log_pos()));
5841
1/2
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
31322 mysql_mutex_unlock(&rli->data_lock);
5842
5843
3/4
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31252 times.
✓ Branch 3 taken 70 times.
31322 if (rli->is_parallel_exec()) {
5844
4/4
✓ Branch 0 taken 18344 times.
✓ Branch 1 taken 12908 times.
✓ Branch 2 taken 5592 times.
✓ Branch 3 taken 12752 times.
31252 bool real_event = server_id && !is_artificial_event();
5845
3/4
✓ Branch 0 taken 5592 times.
✓ Branch 1 taken 25660 times.
✓ Branch 2 taken 31252 times.
✗ Branch 3 not taken.
36844 rli->reset_notified_checkpoint(
5846 5592 0, real_event ? common_header->when.tv_sec + (time_t)exec_time : 0,
5847 real_event);
5848 }
5849
5850 /*
5851 Reset thd->variables.option_bits and sql_mode etc, because this could be
5852 the signal of a master's downgrade from 5.0 to 4.0. However, no need to
5853 reset rli_description_event: indeed, if the next master is 5.0
5854 (even 5.0.1) we will soon get a Format_desc; if the next master is 4.0
5855 then the events are in the slave's format (conversion).
5856 */
5857
1/2
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
31322 set_slave_thread_options(thd);
5858
1/2
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
31322 set_slave_thread_default_charset(thd, rli);
5859 31322 thd->variables.sql_mode = global_system_variables.sql_mode;
5860 31322 thd->variables.auto_increment_increment =
5861 31322 thd->variables.auto_increment_offset = 1;
5862 /*
5863 Rotate_log_events are generated on Slaves with server_id=0
5864 for all the ignored events, so that the positions in the repository
5865 is updated properly even for ignored events.
5866
5867 This kind of Rotate_log_event is generated when
5868
5869 1) the event is generated on the same host and reached due
5870 to circular replication (server_id == ::server_id)
5871
5872 2) the event is from the host which is listed in ignore_server_ids
5873
5874 3) IO thread is receiving HEARTBEAT event from the master
5875
5876 4) IO thread is receiving PREVIOUS_GTID_LOG_EVENT from the master.
5877
5878 We have to free thd's mem_root here after we update the positions
5879 in the repository table. Otherwise, imagine a situation where
5880 Slave is keep getting ignored events only and no other (non-ignored)
5881 events from the Master, Slave never executes free_root (that generally
5882 happens from Query_log_event::do_apply_event or
5883 Rows_log_event::do_apply_event when they find end of the group event).
5884 */
5885
3/4
✓ Branch 0 taken 12937 times.
✓ Branch 1 taken 18385 times.
✓ Branch 2 taken 12937 times.
✗ Branch 3 not taken.
31322 if (server_id == 0) thd->mem_root->ClearForReuse();
5886 } else
5887 23216 rli->inc_event_relay_log_pos();
5888
5889 54538 err:
5890 54538 return error;
5891 54538 }
5892
5893 54733 Log_event::enum_skip_reason Rotate_log_event::do_shall_skip(
5894 Relay_log_info *rli) {
5895 54733 enum_skip_reason reason = Log_event::do_shall_skip(rli);
5896
5897
2/3
✓ Branch 0 taken 36719 times.
✓ Branch 1 taken 18014 times.
✗ Branch 2 not taken.
54733 switch (reason) {
5898 36719 case Log_event::EVENT_SKIP_NOT:
5899 case Log_event::EVENT_SKIP_COUNT:
5900 36719 return Log_event::EVENT_SKIP_NOT;
5901
5902 18014 case Log_event::EVENT_SKIP_IGNORE:
5903 18014 return Log_event::EVENT_SKIP_IGNORE;
5904 }
5905 assert(0);
5906 return Log_event::EVENT_SKIP_NOT; // To keep compiler happy
5907 }
5908
5909 /**************************************************************************
5910 Intvar_log_event methods
5911 **************************************************************************/
5912
5913 /*
5914 Intvar_log_event::pack_info()
5915 */
5916
5917 22092 int Intvar_log_event::pack_info(Protocol *protocol) {
5918 char buf[256], *pos;
5919
2/4
✓ Branch 0 taken 22092 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22092 times.
✗ Branch 3 not taken.
22092 pos = strmake(buf, (get_var_type_string()).c_str(), sizeof(buf) - 23);
5920 22092 *pos++ = '=';
5921
1/2
✓ Branch 0 taken 22092 times.
✗ Branch 1 not taken.
22092 pos = longlong10_to_str(val, pos, -10);
5922
1/2
✓ Branch 0 taken 22092 times.
✗ Branch 1 not taken.
22092 protocol->store_string(buf, (uint)(pos - buf), &my_charset_bin);
5923 22092 return 0;
5924 }
5925 #endif // MYSQL_SERVER
5926
5927 /*
5928 Intvar_log_event::Intvar_log_event()
5929 */
5930 102707 Intvar_log_event::Intvar_log_event(
5931 102707 const char *buf, const Format_description_event *description_event)
5932 : binary_log::Intvar_event(buf, description_event),
5933
1/2
✓ Branch 0 taken 82482 times.
✗ Branch 1 not taken.
102707 Log_event(header(), footer()) {
5934
1/2
✓ Branch 0 taken 102707 times.
✗ Branch 1 not taken.
102707 DBUG_TRACE;
5935 102707 }
5936
5937 /*
5938 Intvar_log_event::write()
5939 */
5940
5941 #ifdef MYSQL_SERVER
5942 87519 bool Intvar_log_event::write(Basic_ostream *ostream) {
5943 uchar buf[9];
5944 87519 buf[I_TYPE_OFFSET] = (uchar)type;
5945 87519 int8store(buf + I_VAL_OFFSET, val);
5946
1/2
✓ Branch 0 taken 87519 times.
✗ Branch 1 not taken.
87519 return (write_header(ostream, sizeof(buf)) ||
5947
3/6
✓ Branch 0 taken 87519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87519 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 87519 times.
✗ Branch 5 not taken.
175038 wrapper_my_b_safe_write(ostream, buf, sizeof(buf)) ||
5948
2/4
✓ Branch 0 taken 87519 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 87519 times.
175038 write_footer(ostream));
5949 }
5950 #endif
5951
5952 /*
5953 Intvar_log_event::print()
5954 */
5955
5956 #ifndef MYSQL_SERVER
5957 20200 void Intvar_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
5958 20200 char llbuff[22] = {0};
5959 20200 const char *msg = nullptr;
5960 20200 IO_CACHE *const head = &print_event_info->head_cache;
5961
5962
2/2
✓ Branch 0 taken 20198 times.
✓ Branch 1 taken 2 times.
20200 if (!print_event_info->short_form) {
5963
1/2
✓ Branch 0 taken 20198 times.
✗ Branch 1 not taken.
20198 print_header(head, print_event_info, false);
5964
1/2
✓ Branch 0 taken 20198 times.
✗ Branch 1 not taken.
20198 my_b_printf(head, "\tIntvar\n");
5965 }
5966
5967
1/2
✓ Branch 0 taken 20200 times.
✗ Branch 1 not taken.
20200 my_b_printf(head, "SET ");
5968
2/3
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 20196 times.
✗ Branch 2 not taken.
20200 switch (type) {
5969 4 case LAST_INSERT_ID_EVENT:
5970 4 msg = "LAST_INSERT_ID";
5971 4 break;
5972 20196 case INSERT_ID_EVENT:
5973 20196 msg = "INSERT_ID";
5974 20196 break;
5975 case INVALID_INT_EVENT:
5976 default: // cannot happen
5977 msg = "INVALID_INT";
5978 break;
5979 }
5980
1/2
✓ Branch 0 taken 20200 times.
✗ Branch 1 not taken.
20200 my_b_printf(head, "%s=%s%s\n", msg, llstr(val, llbuff),
5981
1/2
✓ Branch 0 taken 20200 times.
✗ Branch 1 not taken.
20200 print_event_info->delimiter);
5982 20200 }
5983 #endif
5984
5985 #if defined(MYSQL_SERVER)
5986
5987 /*
5988 Intvar_log_event::do_apply_event()
5989 */
5990
5991 38002 int Intvar_log_event::do_apply_event(Relay_log_info const *rli) {
5992 /*
5993 We are now in a statement until the associated query log event has
5994 been processed.
5995 */
5996 38002 const_cast<Relay_log_info *>(rli)->set_flag(Relay_log_info::IN_STMT);
5997
5998
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 37988 times.
38002 if (rli->deferred_events_collecting) return rli->deferred_events->add(this);
5999
6000
2/3
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 37898 times.
✗ Branch 2 not taken.
37988 switch (type) {
6001 90 case LAST_INSERT_ID_EVENT:
6002 90 thd->first_successful_insert_id_in_prev_stmt = val;
6003 90 break;
6004 37898 case INSERT_ID_EVENT:
6005 37898 thd->force_one_auto_inc_interval(val);
6006 37898 break;
6007 }
6008 37988 return 0;
6009 }
6010
6011 2 int Intvar_log_event::do_update_pos(Relay_log_info *rli) {
6012 2 rli->inc_event_relay_log_pos();
6013 2 return 0;
6014 }
6015
6016 37995 Log_event::enum_skip_reason Intvar_log_event::do_shall_skip(
6017 Relay_log_info *rli) {
6018 /*
6019 It is a common error to set the slave skip counter to 1 instead of
6020 2 when recovering from an insert which used a auto increment,
6021 rand, or user var. Therefore, if the slave skip counter is 1, we
6022 just say that this event should be skipped by ignoring it, meaning
6023 that we do not change the value of the slave skip counter since it
6024 will be decreased by the following insert event.
6025 */
6026 37995 return continue_group(rli);
6027 }
6028
6029 /**************************************************************************
6030 Rand_log_event methods
6031 **************************************************************************/
6032
6033 1 int Rand_log_event::pack_info(Protocol *protocol) {
6034 char buf1[256], *pos;
6035 1 pos = my_stpcpy(buf1, "rand_seed1=");
6036
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 pos = longlong10_to_str(seed1, pos, 10);
6037 1 pos = my_stpcpy(pos, ",rand_seed2=");
6038
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 pos = longlong10_to_str(seed2, pos, 10);
6039
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 protocol->store_string(buf1, (uint)(pos - buf1), &my_charset_bin);
6040 1 return 0;
6041 }
6042 #endif // MYSQL_SERVER
6043
6044 1001 Rand_log_event::Rand_log_event(
6045 1001 const char *buf, const Format_description_event *description_event)
6046 : binary_log::Rand_event(buf, description_event),
6047
1/2
✓ Branch 0 taken 994 times.
✗ Branch 1 not taken.
1001 Log_event(header(), footer()) {
6048
1/2
✓ Branch 0 taken 1001 times.
✗ Branch 1 not taken.
1001 DBUG_TRACE;
6049 1001 }
6050
6051 #ifdef MYSQL_SERVER
6052 2098 bool Rand_log_event::write(Basic_ostream *ostream) {
6053 uchar buf[16];
6054 2098 int8store(buf + RAND_SEED1_OFFSET, seed1);
6055 2098 int8store(buf + RAND_SEED2_OFFSET, seed2);
6056
1/2
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
2098 return (write_header(ostream, sizeof(buf)) ||
6057
3/6
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2098 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2098 times.
✗ Branch 5 not taken.
4196 wrapper_my_b_safe_write(ostream, buf, sizeof(buf)) ||
6058
2/4
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2098 times.
4196 write_footer(ostream));
6059 }
6060 #endif
6061
6062 #ifndef MYSQL_SERVER
6063 4 void Rand_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
6064 4 IO_CACHE *const head = &print_event_info->head_cache;
6065
6066 char llbuff[22], llbuff2[22];
6067
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!print_event_info->short_form) {
6068
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 print_header(head, print_event_info, false);
6069
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_b_printf(head, "\tRand\n");
6070 }
6071
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_b_printf(head, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s%s\n",
6072
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 llstr(seed1, llbuff), llstr(seed2, llbuff2),
6073
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 print_event_info->delimiter);
6074 4 }
6075 #endif /* !MYSQL_SERVER */
6076
6077 #if defined(MYSQL_SERVER)
6078 992 int Rand_log_event::do_apply_event(Relay_log_info const *rli) {
6079 /*
6080 We are now in a statement until the associated query log event has
6081 been processed.
6082 */
6083 992 const_cast<Relay_log_info *>(rli)->set_flag(Relay_log_info::IN_STMT);
6084
6085
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 991 times.
992 if (rli->deferred_events_collecting) return rli->deferred_events->add(this);
6086
6087 991 thd->rand.seed1 = (ulong)seed1;
6088 991 thd->rand.seed2 = (ulong)seed2;
6089 991 return 0;
6090 }
6091
6092 int Rand_log_event::do_update_pos(Relay_log_info *rli) {
6093 rli->inc_event_relay_log_pos();
6094 return 0;
6095 }
6096
6097 992 Log_event::enum_skip_reason Rand_log_event::do_shall_skip(Relay_log_info *rli) {
6098 /*
6099 It is a common error to set the slave skip counter to 1 instead of
6100 2 when recovering from an insert which used a auto increment,
6101 rand, or user var. Therefore, if the slave skip counter is 1, we
6102 just say that this event should be skipped by ignoring it, meaning
6103 that we do not change the value of the slave skip counter since it
6104 will be decreased by the following insert event.
6105 */
6106 992 return continue_group(rli);
6107 }
6108
6109 /**
6110 Exec deferred Int-, Rand- and User- var events prefixing
6111 a Query-log-event event.
6112
6113 @param thd THD handle
6114
6115 @return false on success, true if a failure in an event applying occurred.
6116 */
6117 579670 bool slave_execute_deferred_events(THD *thd) {
6118 579670 bool res = false;
6119 579670 Relay_log_info *rli = thd->rli_slave;
6120
6121
4/6
✓ Branch 0 taken 579712 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1210 times.
✓ Branch 3 taken 578502 times.
✓ Branch 4 taken 1581 times.
✗ Branch 5 not taken.
579670 assert(rli && (!rli->deferred_events_collecting || rli->deferred_events));
6122
6123
4/6
✓ Branch 0 taken 1210 times.
✓ Branch 1 taken 578873 times.
✓ Branch 2 taken 1300 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 580228 times.
✗ Branch 5 not taken.
580083 if (!rli->deferred_events_collecting || rli->deferred_events->is_empty())
6124 580228 return res;
6125
6126 res = rli->deferred_events->execute(rli);
6127 9 rli->deferred_events->rewind();
6128 9 return res;
6129 }
6130
6131 /**************************************************************************
6132 Xid_log_event methods
6133 **************************************************************************/
6134
6135 8121 int Xid_log_event::pack_info(Protocol *protocol) {
6136 char buf[128], *pos;
6137 8121 pos = my_stpcpy(buf, "COMMIT /* xid=");
6138
1/2
✓ Branch 0 taken 8121 times.
✗ Branch 1 not taken.
8121 pos = longlong10_to_str(xid, pos, 10);
6139 8121 pos = my_stpcpy(pos, " */");
6140
1/2
✓ Branch 0 taken 8121 times.
✗ Branch 1 not taken.
8121 protocol->store_string(buf, (uint)(pos - buf), &my_charset_bin);
6141 8121 return 0;
6142 }
6143 #endif // MYSQL_SERVER
6144
6145 2991361 Xid_log_event::Xid_log_event(const char *buf,
6146 2991361 const Format_description_event *description_event)
6147 : binary_log::Xid_event(buf, description_event),
6148
1/2
✓ Branch 0 taken 2991361 times.
✗ Branch 1 not taken.
2991361 Xid_apply_log_event(header(), footer()) {
6149
1/2
✓ Branch 0 taken 2991361 times.
✗ Branch 1 not taken.
2991361 DBUG_TRACE;
6150 2991361 }
6151
6152 #ifdef MYSQL_SERVER
6153 5119890 bool Xid_log_event::write(Basic_ostream *ostream) {
6154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5119943 times.
5119890 DBUG_EXECUTE_IF("do_not_write_xid", return 0;);
6155 5119943 return (write_header(ostream, sizeof(xid)) ||
6156
2/4
✓ Branch 0 taken 5120187 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5120166 times.
✗ Branch 3 not taken.
10240355 wrapper_my_b_safe_write(ostream, (uchar *)&xid, sizeof(xid)) ||
6157
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5120168 times.
10240334 write_footer(ostream));
6158 }
6159 #endif
6160
6161 #ifndef MYSQL_SERVER
6162 18823 void Xid_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
6163 18823 IO_CACHE *const head = &print_event_info->head_cache;
6164
6165
2/2
✓ Branch 0 taken 18306 times.
✓ Branch 1 taken 517 times.
18823 if (!print_event_info->short_form) {
6166 char buf[64];
6167
1/2
✓ Branch 0 taken 18306 times.
✗ Branch 1 not taken.
18306 longlong10_to_str(xid, buf, 10);
6168
6169
1/2
✓ Branch 0 taken 18306 times.
✗ Branch 1 not taken.
18306 print_header(head, print_event_info, false);
6170
1/2
✓ Branch 0 taken 18306 times.
✗ Branch 1 not taken.
18306 my_b_printf(head, "\tXid = %s\n", buf);
6171 }
6172 18823 my_b_printf(head, "COMMIT%s\n", print_event_info->delimiter);
6173 18823 }
6174 #endif /* !MYSQL_SERVER */
6175
6176 #if defined(MYSQL_SERVER)
6177 /**
6178 The methods combines few commit actions to make it usable
6179 as in the single- so multi- threaded case.
6180
6181 @param thd_arg a pointer to THD handle
6182 @return false as success and
6183 true as an error
6184 */
6185
6186 191046 bool Xid_log_event::do_commit(THD *thd_arg) {
6187
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 191044 times.
191046 DBUG_EXECUTE_IF("dbug.reached_commit",
6188 { DBUG_SET("+d,dbug.enabled_commit"); });
6189 191046 bool error = trans_commit(thd_arg); /* Automatically rolls back on error. */
6190
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 190767 times.
190435 DBUG_EXECUTE_IF("crash_after_apply",
6191 sql_print_information("Crashing crash_after_apply.");
6192 DBUG_SUICIDE(););
6193 190767 thd_arg->mdl_context.release_transactional_locks();
6194
6195 190990 error |= (mysql_bin_log.gtid_end_transaction(thd_arg) != 0);
6196
6197 /*
6198 The parser executing a SQLCOM_COMMIT or SQLCOM_ROLLBACK will reset the
6199 tx isolation level and access mode when the statement is finishing a
6200 transaction.
6201
6202 For replicated workload, when dealing with pure transactional workloads,
6203 there will be no QUERY(COMMIT) finishing a transaction, but a
6204 Xid_log_event instead.
6205
6206 So, if the slave applier changed the current transaction isolation level,
6207 it needs to be restored to the session default value once the current
6208 transaction has been committed.
6209 */
6210 190980 trans_reset_one_shot_chistics(thd);
6211
6212 /*
6213 Increment the global status commit count variable
6214 */
6215
2/2
✓ Branch 0 taken 190860 times.
✓ Branch 1 taken 131 times.
190991 if (!error) thd_arg->status_var.com_stat[SQLCOM_COMMIT]++;
6216
6217 190991 return error;
6218 }
6219
6220 /**
6221 Worker commits Xid transaction and in case of its transactional
6222 info table marks the current group as done in the Coordinator's
6223 Group Assigned Queue.
6224
6225 @return zero as success or non-zero as an error
6226 */
6227 191359 int Xid_apply_log_event::do_apply_event_worker(Slave_worker *w) {
6228
1/2
✓ Branch 0 taken 191370 times.
✗ Branch 1 not taken.
191359 DBUG_TRACE;
6229 191370 int error = 0;
6230 191370 bool skipped_commit_pos = true;
6231
6232
1/2
✓ Branch 0 taken 191370 times.
✗ Branch 1 not taken.
191370 lex_start(thd);
6233
1/2
✓ Branch 0 taken 191371 times.
✗ Branch 1 not taken.
191370 mysql_reset_thd_for_next_command(thd);
6234 191371 Slave_committed_queue *coordinator_gaq = w->c_rli->gaq;
6235
6236 /* For a slave Xid_log_event is COMMIT */
6237
1/2
✓ Branch 0 taken 191371 times.
✗ Branch 1 not taken.
191371 query_logger.general_log_print(thd, COM_QUERY,
6238 "COMMIT /* implicit, from Xid_log_event */");
6239
6240
3/8
✓ Branch 0 taken 191371 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 191371 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 191371 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
191371 DBUG_PRINT(
6241 "mts",
6242 ("do_apply group master %s %llu group relay %s %llu event %s %llu.",
6243 w->get_group_master_log_name(), w->get_group_master_log_pos(),
6244 w->get_group_relay_log_name(), w->get_group_relay_log_pos(),
6245 w->get_event_relay_log_name(), w->get_event_relay_log_pos()));
6246
6247
5/8
✓ Branch 0 taken 191371 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 191341 times.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
191371 DBUG_EXECUTE_IF("crash_before_update_pos",
6248 sql_print_information("Crashing crash_before_update_pos.");
6249 DBUG_SUICIDE(););
6250
6251
2/4
✓ Branch 0 taken 191339 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 191339 times.
191341 DBUG_EXECUTE_IF("simulate_commit_failure", {
6252 thd->get_transaction()->xid_state()->set_state(XID_STATE::XA_IDLE);
6253 });
6254
6255 191339 ulong gaq_idx = mts_group_idx;
6256
1/2
✓ Branch 0 taken 191341 times.
✗ Branch 1 not taken.
191339 Slave_job_group *ptr_group = coordinator_gaq->get_job_group(gaq_idx);
6257
6258
5/6
✓ Branch 0 taken 191338 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 191013 times.
✓ Branch 3 taken 325 times.
✓ Branch 4 taken 190961 times.
✓ Branch 5 taken 378 times.
382355 if (!thd->get_transaction()->xid_state()->check_in_xa(false) &&
6259
3/4
✓ Branch 0 taken 191014 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 190959 times.
✓ Branch 3 taken 55 times.
191013 w->is_transactional()) {
6260 /*
6261 Regular (not XA) transaction updates the transactional info table
6262 along with the main transaction. Otherwise, the local flag turned
6263 and given its value the info table is updated after do_commit.
6264 todo: the flag won't be need upon the full xa crash-safety bug76233
6265 gets fixed.
6266 */
6267 190961 skipped_commit_pos = false;
6268
4/6
✓ Branch 0 taken 190961 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 190959 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 190956 times.
190961 if ((error = w->commit_positions(this, ptr_group, w->is_transactional())))
6269 3 goto err;
6270 }
6271
6272
3/8
✓ Branch 0 taken 191337 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 191337 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 191337 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
191334 DBUG_PRINT(
6273 "mts",
6274 ("do_apply group master %s %llu group relay %s %llu event %s %llu.",
6275 w->get_group_master_log_name(), w->get_group_master_log_pos(),
6276 w->get_group_relay_log_name(), w->get_group_relay_log_pos(),
6277 w->get_event_relay_log_name(), w->get_event_relay_log_pos()));
6278
6279
5/8
✓ Branch 0 taken 191338 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 191308 times.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
191337 DBUG_EXECUTE_IF(
6280 "crash_after_update_pos_before_apply",
6281 sql_print_information("Crashing crash_after_update_pos_before_apply.");
6282 DBUG_SUICIDE(););
6283
6284
1/2
✓ Branch 0 taken 191083 times.
✗ Branch 1 not taken.
191308 error = do_commit(thd);
6285
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 190943 times.
191083 if (error) {
6286
3/4
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 133 times.
✗ Branch 3 not taken.
140 if (!skipped_commit_pos) w->rollback_positions(ptr_group);
6287 } else {
6288
5/8
✓ Branch 0 taken 191062 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 191032 times.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
190943 DBUG_EXECUTE_IF(
6289 "crash_after_commit_before_update_pos",
6290 sql_print_information("Crashing "
6291 "crash_after_commit_before_update_pos.");
6292 DBUG_SUICIDE(););
6293
2/2
✓ Branch 0 taken 190661 times.
✓ Branch 1 taken 371 times.
191032 if (skipped_commit_pos)
6294
2/4
✓ Branch 0 taken 371 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 371 times.
✗ Branch 3 not taken.
371 error = w->commit_positions(this, ptr_group, w->is_transactional());
6295 }
6296 190661 err:
6297 191212 return error;
6298 191175 }
6299
6300 81 int Xid_apply_log_event::do_apply_event(Relay_log_info const *rli) {
6301
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 DBUG_TRACE;
6302 81 int error = 0;
6303 char saved_group_master_log_name[FN_REFLEN];
6304 char saved_group_relay_log_name[FN_REFLEN];
6305 volatile my_off_t saved_group_master_log_pos;
6306 volatile my_off_t saved_group_relay_log_pos;
6307
6308 char new_group_master_log_name[FN_REFLEN];
6309 char new_group_relay_log_name[FN_REFLEN];
6310 volatile my_off_t new_group_master_log_pos;
6311 volatile my_off_t new_group_relay_log_pos;
6312
6313
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 lex_start(thd);
6314
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 mysql_reset_thd_for_next_command(thd);
6315 /*
6316 Anonymous GTID ownership may be released here if the last
6317 statement before XID updated a non-transactional table and was
6318 written to the binary log as a separate transaction (either
6319 because binlog_format=row or because
6320 binlog_direct_non_transactional_updates=1). So we need to
6321 re-acquire anonymous ownership.
6322 */
6323
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 gtid_reacquire_ownership_if_anonymous(thd);
6324 81 Relay_log_info *rli_ptr = const_cast<Relay_log_info *>(rli);
6325
6326 /* For a slave Xid_log_event is COMMIT */
6327
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 query_logger.general_log_print(thd, COM_QUERY,
6328 "COMMIT /* implicit, from Xid_log_event */");
6329
6330
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 mysql_mutex_lock(&rli_ptr->data_lock);
6331
6332 /*
6333 Save the rli positions. We need them to temporarily reset the positions
6334 just before the commit.
6335 */
6336
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 strmake(saved_group_master_log_name, rli_ptr->get_group_master_log_name(),
6337 FN_REFLEN - 1);
6338 81 saved_group_master_log_pos = rli_ptr->get_group_master_log_pos();
6339
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 strmake(saved_group_relay_log_name, rli_ptr->get_group_relay_log_name(),
6340 FN_REFLEN - 1);
6341 81 saved_group_relay_log_pos = rli_ptr->get_group_relay_log_pos();
6342
6343
3/8
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 81 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
81 DBUG_PRINT(
6344 "info",
6345 ("do_apply group master %s %llu group relay %s %llu event %s %llu\n",
6346 rli_ptr->get_group_master_log_name(),
6347 rli_ptr->get_group_master_log_pos(), rli_ptr->get_group_relay_log_name(),
6348 rli_ptr->get_group_relay_log_pos(), rli_ptr->get_event_relay_log_name(),
6349 rli_ptr->get_event_relay_log_pos()));
6350
6351
2/8
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
81 DBUG_EXECUTE_IF("crash_before_update_pos",
6352 sql_print_information("Crashing crash_before_update_pos.");
6353 DBUG_SUICIDE(););
6354
6355 /*
6356 We need to update the positions in here to make it transactional.
6357 */
6358 81 rli_ptr->inc_event_relay_log_pos();
6359 81 rli_ptr->set_group_relay_log_pos(rli_ptr->get_event_relay_log_pos());
6360
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 rli_ptr->set_group_relay_log_name(rli_ptr->get_event_relay_log_name());
6361
6362
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 if (common_header->log_pos) // 3.23 binlogs don't have log_posx
6363 81 rli_ptr->set_group_master_log_pos(common_header->log_pos);
6364
6365
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 const bool already_logged_transaction = is_already_logged_transaction(thd);
6366 /*
6367 rli repository being transactional means replication is crash safe.
6368 Positions are written into transactional tables ahead of commit and the
6369 changes are made permanent during commit.
6370 XA transactional does not actually commit so has to defer its flush_info().
6371 */
6372
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 if (!thd->get_transaction()->xid_state()->check_in_xa(false) &&
6373
9/10
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 78 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 63 times.
✓ Branch 7 taken 15 times.
✓ Branch 8 taken 63 times.
✓ Branch 9 taken 18 times.
81 rli_ptr->is_transactional() && !already_logged_transaction) {
6374 63 if ((error =
6375
2/4
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 63 times.
63 rli_ptr->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT)))
6376 goto err;
6377 }
6378
6379
3/8
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 81 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
81 DBUG_PRINT(
6380 "info",
6381 ("do_apply group master %s %llu group relay %s %llu event %s %llu\n",
6382 rli_ptr->get_group_master_log_name(),
6383 rli_ptr->get_group_master_log_pos(), rli_ptr->get_group_relay_log_name(),
6384 rli_ptr->get_group_relay_log_pos(), rli_ptr->get_event_relay_log_name(),
6385 rli_ptr->get_event_relay_log_pos()));
6386
6387
2/8
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
81 DBUG_EXECUTE_IF(
6388 "crash_after_update_pos_before_apply",
6389 sql_print_information("Crashing crash_after_update_pos_before_apply.");
6390 DBUG_SUICIDE(););
6391
6392 /**
6393 Commit operation expects the global transaction state variable 'xa_state'to
6394 be set to 'XA_NOTR'. In order to simulate commit failure we set
6395 the 'xa_state' to 'XA_IDLE' so that the commit reports 'ER_XAER_RMFAIL'
6396 error.
6397 */
6398
2/4
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
81 DBUG_EXECUTE_IF("simulate_commit_failure", {
6399 thd->get_transaction()->xid_state()->set_state(XID_STATE::XA_IDLE);
6400 });
6401
6402 /*
6403 Save the new rli positions. These positions will be set back to group*
6404 positions on successful completion of the commit operation.
6405 */
6406
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 strmake(new_group_master_log_name, rli_ptr->get_group_master_log_name(),
6407 FN_REFLEN - 1);
6408 81 new_group_master_log_pos = rli_ptr->get_group_master_log_pos();
6409
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 strmake(new_group_relay_log_name, rli_ptr->get_group_relay_log_name(),
6410 FN_REFLEN - 1);
6411 81 new_group_relay_log_pos = rli_ptr->get_group_relay_log_pos();
6412 /*
6413 Rollback positions in memory just before commit. Position values will be
6414 reset to their new values only on successful commit operation.
6415 */
6416
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 rli_ptr->set_group_master_log_name(saved_group_master_log_name);
6417 81 rli_ptr->set_group_master_log_pos(saved_group_master_log_pos);
6418
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 rli_ptr->notify_group_master_log_name_update();
6419
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 rli_ptr->set_group_relay_log_name(saved_group_relay_log_name);
6420 81 rli_ptr->set_group_relay_log_pos(saved_group_relay_log_pos);
6421
6422
3/8
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 81 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
81 DBUG_PRINT("info", ("Rolling back to group master %s %llu group relay %s"
6423 " %llu\n",
6424 rli_ptr->get_group_master_log_name(),
6425 rli_ptr->get_group_master_log_pos(),
6426 rli_ptr->get_group_relay_log_name(),
6427 rli_ptr->get_group_relay_log_pos()));
6428
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 mysql_mutex_unlock(&rli_ptr->data_lock);
6429
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 error = do_commit(thd);
6430
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 mysql_mutex_lock(&rli_ptr->data_lock);
6431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if (error) {
6432 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
6433 "Error in Xid_log_event: Commit could not be completed, '%s'",
6434 thd->get_stmt_da()->message_text());
6435 } else {
6436
2/8
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
81 DBUG_EXECUTE_IF(
6437 "crash_after_commit_before_update_pos",
6438 sql_print_information("Crashing "
6439 "crash_after_commit_before_update_pos.");
6440 DBUG_SUICIDE(););
6441 /* Update positions on successful commit */
6442
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 rli_ptr->set_group_master_log_name(new_group_master_log_name);
6443 81 rli_ptr->set_group_master_log_pos(new_group_master_log_pos);
6444
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 rli_ptr->notify_group_master_log_name_update();
6445
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 rli_ptr->set_group_relay_log_name(new_group_relay_log_name);
6446 81 rli_ptr->set_group_relay_log_pos(new_group_relay_log_pos);
6447
6448
3/8
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 81 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
81 DBUG_PRINT("info", ("Updating positions on succesful commit to group master"
6449 " %s %llu group relay %s %llu\n",
6450 rli_ptr->get_group_master_log_name(),
6451 rli_ptr->get_group_master_log_pos(),
6452 rli_ptr->get_group_relay_log_name(),
6453 rli_ptr->get_group_relay_log_pos()));
6454
6455 /*
6456 For transactional repository the positions are flushed ahead of commit.
6457 Where as for non transactional rli repository the positions are flushed
6458 only on successful commit.
6459 */
6460
6/8
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 80 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 80 times.
✓ Branch 7 taken 1 times.
81 if (!rli_ptr->is_transactional() && !already_logged_transaction)
6461
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli_ptr->flush_info(Relay_log_info::RLI_FLUSH_NO_OPTION);
6462 }
6463 80 err:
6464 // This is Bug#24588741 fix:
6465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if (rli_ptr->is_group_master_log_pos_invalid)
6466 rli_ptr->is_group_master_log_pos_invalid = false;
6467
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 mysql_cond_broadcast(&rli_ptr->data_cond);
6468
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 mysql_mutex_unlock(&rli_ptr->data_lock);
6469
6470 81 return error;
6471 81 }
6472
6473 192395 Log_event::enum_skip_reason Xid_apply_log_event::do_shall_skip(
6474 Relay_log_info *rli) {
6475
1/2
✓ Branch 0 taken 192395 times.
✗ Branch 1 not taken.
192395 DBUG_TRACE;
6476
2/2
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 192081 times.
192395 if (rli->slave_skip_counter > 0) {
6477 314 thd->variables.option_bits &= ~OPTION_BEGIN;
6478 314 return Log_event::EVENT_SKIP_COUNT;
6479 }
6480
1/2
✓ Branch 0 taken 192081 times.
✗ Branch 1 not taken.
192081 return Log_event::do_shall_skip(rli);
6481 192395 }
6482
6483 /**************************************************************************
6484 XA_prepare_log_event methods
6485 **************************************************************************/
6486
6487 100 int XA_prepare_log_event::pack_info(Protocol *protocol) {
6488 char buf[ser_buf_size];
6489 char query[sizeof("XA COMMIT ONE PHASE") + 1 + sizeof(buf)];
6490
6491 /* RHS of the following assert is unknown to client sources */
6492 static_assert(ser_buf_size == XID::ser_buf_size, "");
6493 100 serialize_xid(buf, my_xid.formatID, my_xid.gtrid_length, my_xid.bqual_length,
6494 100 my_xid.data);
6495
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 69 times.
100 sprintf(query, (one_phase ? "XA COMMIT %s ONE PHASE" : "XA PREPARE %s"), buf);
6496
6497
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 protocol->store_string(query, strlen(query), &my_charset_bin);
6498 100 return 0;
6499 }
6500
6501 634 bool XA_prepare_log_event::write(Basic_ostream *ostream) {
6502 634 uint8 one_byte = one_phase;
6503 uchar buf_f[4];
6504 uchar buf_g[4];
6505 uchar buf_b[4];
6506 634 int4store(buf_f, static_cast<XID *>(xid)->get_format_id());
6507 634 int4store(buf_g, static_cast<XID *>(xid)->get_gtrid_length());
6508 634 int4store(buf_b, static_cast<XID *>(xid)->get_bqual_length());
6509
6510 assert(xid_bufs_size == sizeof(buf_f) + sizeof(buf_g) + sizeof(buf_b));
6511
6512 1902 return write_header(ostream,
6513 sizeof(one_byte) + xid_bufs_size +
6514
1/2
✓ Branch 0 taken 634 times.
✗ Branch 1 not taken.
1268 static_cast<XID *>(xid)->get_gtrid_length() +
6515 634 static_cast<XID *>(xid)->get_bqual_length()) ||
6516
2/4
✓ Branch 0 taken 634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 634 times.
✗ Branch 3 not taken.
634 wrapper_my_b_safe_write(ostream, &one_byte, sizeof(one_byte)) ||
6517
2/4
✓ Branch 0 taken 634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 634 times.
✗ Branch 3 not taken.
634 wrapper_my_b_safe_write(ostream, buf_f, sizeof(buf_f)) ||
6518
2/4
✓ Branch 0 taken 634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 634 times.
✗ Branch 3 not taken.
634 wrapper_my_b_safe_write(ostream, buf_g, sizeof(buf_g)) ||
6519
2/4
✓ Branch 0 taken 634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 634 times.
✗ Branch 3 not taken.
634 wrapper_my_b_safe_write(ostream, buf_b, sizeof(buf_b)) ||
6520
2/4
✓ Branch 0 taken 634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 634 times.
✗ Branch 3 not taken.
634 wrapper_my_b_safe_write(
6521 ostream,
6522 634 pointer_cast<const uchar *>(static_cast<XID *>(xid)->get_data()),
6523 1268 static_cast<XID *>(xid)->get_gtrid_length() +
6524
1/2
✓ Branch 0 taken 634 times.
✗ Branch 1 not taken.
1902 static_cast<XID *>(xid)->get_bqual_length()) ||
6525
2/4
✓ Branch 0 taken 634 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 634 times.
1268 write_footer(ostream);
6526 }
6527 #endif // MYSQL_SERVER
6528
6529 #ifndef MYSQL_SERVER
6530 5 void XA_prepare_log_event::print(FILE *,
6531 PRINT_EVENT_INFO *print_event_info) const {
6532 5 IO_CACHE *const head = &print_event_info->head_cache;
6533 char buf[ser_buf_size];
6534
6535
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 print_header(head, print_event_info, false);
6536 5 serialize_xid(buf, my_xid.formatID, my_xid.gtrid_length, my_xid.bqual_length,
6537 5 my_xid.data);
6538
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_b_printf(head, "\tXA PREPARE %s\n", buf);
6539
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_b_printf(
6540 5 head, one_phase ? "XA COMMIT %s ONE PHASE\n%s\n" : "XA PREPARE %s\n%s\n",
6541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 buf, print_event_info->delimiter);
6542 5 }
6543 #endif /* !MYSQL_SERVER */
6544
6545 #if defined(MYSQL_SERVER)
6546
6547 /**
6548 Differs from Xid_log_event::do_commit in that it carries out
6549 XA prepare (not the commit).
6550 It also can commit on one phase when the event's member @c one_phase
6551 set to true.
6552
6553 @param thd_arg a pointer to THD handle
6554 @return false as success and
6555 true as an error
6556 */
6557
6558 341 bool XA_prepare_log_event::do_commit(THD *thd_arg) {
6559
1/2
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
341 enum_gtid_statement_status state = gtid_pre_statement_checks(thd_arg);
6560
2/2
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 9 times.
341 if (state == GTID_STATEMENT_EXECUTE) {
6561
3/4
✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 329 times.
332 if (gtid_pre_statement_post_implicit_commit_checks(thd_arg))
6562 3 state = GTID_STATEMENT_CANCEL;
6563 }
6564
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 338 times.
341 if (state == GTID_STATEMENT_CANCEL) {
6565 3 uint error = thd_arg->get_stmt_da()->mysql_errno();
6566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(error != 0);
6567
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 thd_arg->rli_slave->report(ERROR_LEVEL, error,
6568 "Error executing XA PREPARE event: '%s'",
6569 thd_arg->get_stmt_da()->message_text());
6570 3 thd_arg->is_slave_error = true;
6571 3 return true;
6572
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 329 times.
338 } else if (state == GTID_STATEMENT_SKIP)
6573 9 return false;
6574
6575 329 bool error = false;
6576 329 xid_t xid;
6577 329 xid.set(my_xid.formatID, my_xid.data, my_xid.gtrid_length,
6578
1/2
✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
329 my_xid.data + my_xid.gtrid_length, my_xid.bqual_length);
6579
2/2
✓ Branch 0 taken 275 times.
✓ Branch 1 taken 54 times.
329 if (!one_phase) {
6580 /*
6581 This is XA-prepare branch.
6582 */
6583 275 thd_arg->lex->sql_command = SQLCOM_XA_PREPARE;
6584
2/4
✓ Branch 0 taken 275 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 275 times.
✗ Branch 3 not taken.
275 thd_arg->lex->m_sql_cmd = new (thd_arg->mem_root) Sql_cmd_xa_prepare(&xid);
6585
1/2
✓ Branch 0 taken 274 times.
✗ Branch 1 not taken.
275 error = thd_arg->lex->m_sql_cmd->execute(thd_arg);
6586 } else {
6587 54 thd_arg->lex->sql_command = SQLCOM_XA_COMMIT;
6588 54 thd_arg->lex->m_sql_cmd =
6589
2/4
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
54 new (thd_arg->mem_root) Sql_cmd_xa_commit(&xid, XA_ONE_PHASE);
6590
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
54 error = thd_arg->lex->m_sql_cmd->execute(thd_arg);
6591 }
6592
6593
3/4
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 320 times.
✗ Branch 3 not taken.
327 if (!error) error = mysql_bin_log.gtid_end_transaction(thd_arg);
6594
6595 327 return error;
6596 }
6597
6598 /**************************************************************************
6599 User_var_log_event methods
6600 **************************************************************************/
6601
6602 62 int User_var_log_event::pack_info(Protocol *protocol) {
6603 62 char *buf = nullptr;
6604 char quoted_id[1 + FN_REFLEN * 2 + 2]; // quoted identifier
6605 size_t id_len =
6606
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 my_strmov_quoted_identifier(this->thd, quoted_id, name, name_len);
6607 62 quoted_id[id_len] = '\0';
6608 62 size_t val_offset = 2 + id_len;
6609 62 size_t event_len = val_offset;
6610
6611
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 61 times.
62 if (is_null) {
6612
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!(buf = (char *)my_malloc(key_memory_log_event, val_offset + 5,
6613 MYF(MY_WME))))
6614 return 1;
6615 1 my_stpcpy(buf + val_offset, "NULL");
6616 1 event_len = val_offset + 4;
6617 } else {
6618
4/5
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
61 switch (type) {
6619 1 case REAL_RESULT:
6620 double real_val;
6621 1 real_val = float8get(val);
6622 2 if (!(buf = (char *)my_malloc(key_memory_log_event,
6623
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 val_offset + MY_GCVT_MAX_FIELD_WIDTH + 1,
6624 MYF(MY_WME))))
6625 return 1;
6626 1 event_len +=
6627
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_gcvt(real_val, MY_GCVT_ARG_DOUBLE, MY_GCVT_MAX_FIELD_WIDTH,
6628 buf + val_offset, nullptr);
6629 1 break;
6630 56 case INT_RESULT:
6631
2/4
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 56 times.
56 if (!(buf = (char *)my_malloc(key_memory_log_event, val_offset + 22,
6632 MYF(MY_WME))))
6633 return 1;
6634
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
112 event_len = longlong10_to_str(
6635 56 uint8korr(val), buf + val_offset,
6636
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 52 times.
56 ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10)) -
6637 buf;
6638 56 break;
6639 1 case DECIMAL_RESULT: {
6640
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!(buf = (char *)my_malloc(key_memory_log_event,
6641 val_offset + DECIMAL_MAX_STR_LENGTH + 1,
6642 MYF(MY_WME))))
6643 return 1;
6644 String str(buf + val_offset, DECIMAL_MAX_STR_LENGTH + 1,
6645 1 &my_charset_bin);
6646 1 my_decimal dec;
6647 1 binary2my_decimal(E_DEC_FATAL_ERROR, (uchar *)(val + 2), &dec, val[0],
6648
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 val[1]);
6649
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_decimal2string(E_DEC_FATAL_ERROR, &dec, &str);
6650 1 event_len = str.length() + val_offset;
6651 1 break;
6652 1 }
6653 3 case STRING_RESULT:
6654 /* 15 is for 'COLLATE' and other chars */
6655 6 buf = (char *)my_malloc(
6656 key_memory_log_event,
6657
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 event_len + val_len * 2 + 1 + 2 * MY_CS_NAME_SIZE + 15,
6658 MYF(MY_WME));
6659 CHARSET_INFO *cs;
6660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!buf) return 1;
6661
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (!(cs = get_charset(charset_number, MYF(0)))) {
6662 my_stpcpy(buf + val_offset, "???");
6663 event_len += 3;
6664 } else {
6665
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 char *p = strxmov(buf + val_offset, "_", cs->csname, " ", NullS);
6666
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 p = str_to_hex(p, val, val_len);
6667
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 p = strxmov(p, " COLLATE ", cs->m_coll_name, NullS);
6668 3 event_len = p - buf;
6669 }
6670 3 break;
6671 case ROW_RESULT:
6672 default:
6673 assert(false);
6674 return 1;
6675 }
6676 }
6677 62 buf[0] = '@';
6678 62 memcpy(buf + 1, quoted_id, id_len);
6679 62 buf[1 + id_len] = '=';
6680
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 protocol->store_string(buf, event_len, &my_charset_bin);
6681
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 my_free(buf);
6682 62 return 0;
6683 }
6684 #endif /* MYSQL_SERVER */
6685
6686 6883 User_var_log_event::User_var_log_event(
6687 6883 const char *buf, const Format_description_event *description_event)
6688 : binary_log::User_var_event(buf, description_event),
6689 27 Log_event(header(), footer())
6690 #ifdef MYSQL_SERVER
6691 ,
6692 6856 deferred(false),
6693
1/2
✓ Branch 0 taken 6856 times.
✗ Branch 1 not taken.
6856 query_id(0)
6694 #endif
6695 {
6696
1/2
✓ Branch 0 taken 6883 times.
✗ Branch 1 not taken.
6883 DBUG_TRACE;
6697 6883 }
6698
6699 #ifdef MYSQL_SERVER
6700 8519 bool User_var_log_event::write(Basic_ostream *ostream) {
6701 char buf[UV_NAME_LEN_SIZE];
6702 char buf1[UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE +
6703 UV_VAL_LEN_SIZE];
6704 8519 uchar buf2[std::max(8, DECIMAL_MAX_FIELD_SIZE + 2)], *pos = buf2;
6705 8519 uint unsigned_len = 0;
6706 uint buf1_length;
6707 ulong event_length;
6708
6709 8519 int4store(buf, name_len);
6710
6711
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 8497 times.
8519 if ((buf1[0] = is_null)) {
6712 22 buf1_length = 1;
6713 22 val_len = 0; // Length of 'pos'
6714 } else {
6715 8497 buf1[1] = type;
6716 8497 int4store(buf1 + 2, charset_number);
6717
6718
4/5
✓ Branch 0 taken 2753 times.
✓ Branch 1 taken 326 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 5402 times.
✗ Branch 4 not taken.
8497 switch (type) {
6719 2753 case REAL_RESULT:
6720 2753 float8store(buf2, *(double *)val);
6721 2753 break;
6722 326 case INT_RESULT:
6723 326 int8store(buf2, *(longlong *)val);
6724 326 unsigned_len = 1;
6725 326 break;
6726 16 case DECIMAL_RESULT: {
6727 16 my_decimal *dec = (my_decimal *)val;
6728 16 dec->sanity_check();
6729 16 buf2[0] = (char)(dec->intg + dec->frac);
6730 16 buf2[1] = (char)dec->frac;
6731
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 decimal2bin(dec, buf2 + 2, buf2[0], buf2[1]);
6732
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 val_len = decimal_bin_size(buf2[0], buf2[1]) + 2;
6733 16 break;
6734 }
6735 5402 case STRING_RESULT:
6736 5402 pos = (uchar *)val;
6737 5402 break;
6738 case ROW_RESULT:
6739 default:
6740 assert(false);
6741 return false;
6742 }
6743 8497 int4store(buf1 + 2 + UV_CHARSET_NUMBER_SIZE, val_len);
6744 8497 buf1_length = 10;
6745 }
6746
6747 8519 event_length = sizeof(buf) + name_len + buf1_length + val_len + unsigned_len;
6748
6749
1/2
✓ Branch 0 taken 8519 times.
✗ Branch 1 not taken.
8519 return (write_header(ostream, event_length) ||
6750
2/4
✓ Branch 0 taken 8519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8519 times.
✗ Branch 3 not taken.
8519 wrapper_my_b_safe_write(ostream, (uchar *)buf, sizeof(buf)) ||
6751
2/4
✓ Branch 0 taken 8519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8519 times.
✗ Branch 3 not taken.
8519 wrapper_my_b_safe_write(ostream, pointer_cast<const uchar *>(name),
6752 8519 name_len) ||
6753
2/4
✓ Branch 0 taken 8519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8519 times.
✗ Branch 3 not taken.
8519 wrapper_my_b_safe_write(ostream, (uchar *)buf1, buf1_length) ||
6754
2/4
✓ Branch 0 taken 8519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8519 times.
✗ Branch 3 not taken.
8519 wrapper_my_b_safe_write(ostream, pos, val_len) ||
6755
3/6
✓ Branch 0 taken 8519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8519 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8519 times.
✗ Branch 5 not taken.
25557 wrapper_my_b_safe_write(ostream, &flags, unsigned_len) ||
6756
2/4
✓ Branch 0 taken 8519 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8519 times.
17038 write_footer(ostream));
6757 }
6758 #endif
6759
6760 /*
6761 User_var_log_event::print()
6762 */
6763
6764 #ifndef MYSQL_SERVER
6765 24 void User_var_log_event::print(FILE *,
6766 PRINT_EVENT_INFO *print_event_info) const {
6767 24 IO_CACHE *const head = &print_event_info->head_cache;
6768 char quoted_id[1 + NAME_LEN * 2 + 2]; // quoted length of the identifier
6769 char name_id[NAME_LEN + 1];
6770 24 size_t quoted_len = 0;
6771
6772
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 15 times.
24 if (!print_event_info->short_form) {
6773
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 print_header(head, print_event_info, false);
6774
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_b_printf(head, "\tUser_var\n");
6775 }
6776 24 my_stpcpy(name_id, name);
6777 24 name_id[name_len] = '\0';
6778
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 my_b_printf(head, "SET @");
6779 quoted_len =
6780
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 my_strmov_quoted_identifier((char *)quoted_id, (const char *)name_id);
6781 24 quoted_id[quoted_len] = '\0';
6782 [[maybe_unused]]
6783
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 int write_res = my_b_write(head, (uchar *)quoted_id, quoted_len);
6784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 assert(write_res == 0);
6785
6786
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 23 times.
24 if (is_null) {
6787
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_b_printf(head, ":=NULL%s\n", print_event_info->delimiter);
6788 } else {
6789
4/5
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
23 switch (type) {
6790 2 case REAL_RESULT:
6791 double real_val;
6792 char real_buf[FMT_G_BUFSIZE(14)];
6793 2 real_val = float8get(val);
6794 2 sprintf(real_buf, "%.14g", real_val);
6795
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_b_printf(head, ":=%s%s\n", real_buf, print_event_info->delimiter);
6796 23 break;
6797 9 case INT_RESULT:
6798 char int_buf[22];
6799
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
18 longlong10_to_str(
6800 9 uint8korr(val), int_buf,
6801
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10));
6802
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_b_printf(head, ":=%s%s\n", int_buf, print_event_info->delimiter);
6803 9 break;
6804 2 case DECIMAL_RESULT: {
6805 char str_buf[DECIMAL_MAX_STR_LENGTH + 1];
6806 2 int str_len = sizeof(str_buf);
6807 2 int precision = (int)val[0];
6808 2 int scale = (int)val[1];
6809 decimal_digit_t dec_buf[10];
6810 decimal_t dec;
6811 2 dec.len = 10;
6812 2 dec.buf = dec_buf;
6813
6814
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 bin2decimal((uchar *)val + 2, &dec, precision, scale);
6815
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 decimal2string(&dec, str_buf, &str_len);
6816
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_b_printf(head, ":=%s%s\n", str_buf, print_event_info->delimiter);
6817 2 break;
6818 }
6819 10 case STRING_RESULT: {
6820 /*
6821 Let's express the string in hex. That's the most robust way. If we
6822 print it in character form instead, we need to escape it with
6823 character_set_client which we don't know (we will know it in 5.0, but
6824 in 4.1 we don't know it easily when we are printing
6825 User_var_log_event). Explanation why we would need to bother with
6826 character_set_client (quoting Bar):
6827 > Note, the parser doesn't switch to another unescaping mode after
6828 > it has met a character set introducer.
6829 > For example, if an SJIS client says something like:
6830 > SET @a= _ucs2 \0a\0b'
6831 > the string constant is still unescaped according to SJIS, not
6832 > according to UCS2.
6833 */
6834 char *hex_str;
6835 CHARSET_INFO *cs;
6836
6837
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 hex_str = (char *)my_malloc(key_memory_log_event, 2 * val_len + 1 + 2,
6838 MYF(MY_WME)); // 2 hex digits / byte
6839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!hex_str) return;
6840
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 str_to_hex(hex_str, val, val_len);
6841 /*
6842 For proper behaviour when mysqlbinlog|mysql, we need to explicitly
6843 specify the variable's collation. It will however cause problems when
6844 people want to mysqlbinlog|mysql into another server not supporting
6845 the character set. But there's not much to do about this and it's
6846 unlikely.
6847 */
6848
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (!(cs = get_charset(charset_number, MYF(0))))
6849 /*
6850 Generate an unusable command (=> syntax error) is probably the best
6851 thing we can do here.
6852 */
6853 my_b_printf(head, ":=???%s\n", print_event_info->delimiter);
6854 else
6855 10 my_b_printf(head, ":=_%s %s COLLATE `%s`%s\n", cs->csname, hex_str,
6856
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 cs->m_coll_name, print_event_info->delimiter);
6857
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 my_free(hex_str);
6858 10 } break;
6859 case ROW_RESULT:
6860 default:
6861 assert(false);
6862 return;
6863 }
6864 }
6865 }
6866 #endif
6867
6868 /*
6869 User_var_log_event::do_apply_event()
6870 */
6871
6872 #if defined(MYSQL_SERVER)
6873 6745 int User_var_log_event::do_apply_event(Relay_log_info const *rli) {
6874
1/2
✓ Branch 0 taken 6745 times.
✗ Branch 1 not taken.
6745 DBUG_TRACE;
6875 6745 Item *it = nullptr;
6876 CHARSET_INFO *charset;
6877 6745 query_id_t sav_query_id = 0; /* memorize orig id when deferred applying */
6878
6879
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6744 times.
6745 if (rli->deferred_events_collecting) {
6880
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 set_deferred(current_thd->query_id);
6881
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 int ret = rli->deferred_events->add(this);
6882 1 return ret;
6883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6744 times.
6744 } else if (is_deferred()) {
6884 sav_query_id = current_thd->query_id;
6885 current_thd->query_id = query_id; /* recreating original time context */
6886 }
6887
6888
2/4
✓ Branch 0 taken 6744 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6744 times.
6744 if (!(charset = get_charset(charset_number, MYF(MY_WME)))) {
6889 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6890 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
6891 "Invalid character set for User var event");
6892 return 1;
6893 }
6894 double real_val;
6895 longlong int_val;
6896
6897 /*
6898 We are now in a statement until the associated query log event has
6899 been processed.
6900 */
6901 6744 const_cast<Relay_log_info *>(rli)->set_flag(Relay_log_info::IN_STMT);
6902
6903
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6734 times.
6744 if (is_null) {
6904
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
20 it = new Item_null();
6905 } else {
6906
4/5
✓ Branch 0 taken 1853 times.
✓ Branch 1 taken 167 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 4707 times.
✗ Branch 4 not taken.
6734 switch (type) {
6907 1853 case REAL_RESULT:
6908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1853 times.
1853 if (val_len != 8) {
6909 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6910 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
6911 "Invalid variable length at User var event");
6912 return 1;
6913 }
6914 1853 real_val = float8get(val);
6915
2/4
✓ Branch 0 taken 1853 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1853 times.
✗ Branch 3 not taken.
1853 it = new Item_float(real_val, 0);
6916 1853 val = (char *)&real_val; // Pointer to value in native format
6917 1853 val_len = 8;
6918 1853 break;
6919 167 case INT_RESULT:
6920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
167 if (val_len != 8) {
6921 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6922 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
6923 "Invalid variable length at User var event");
6924 return 1;
6925 }
6926 167 int_val = (longlong)uint8korr(val);
6927
2/4
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 167 times.
✗ Branch 3 not taken.
167 it = new Item_int(int_val);
6928 167 val = (char *)&int_val; // Pointer to value in native format
6929 167 val_len = 8;
6930 167 break;
6931 7 case DECIMAL_RESULT: {
6932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (val_len < 3) {
6933 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6934 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
6935 "Invalid variable length at User var event");
6936 return 1;
6937 }
6938
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 Item_decimal *dec = new Item_decimal((uchar *)val + 2, val[0], val[1]);
6939 7 it = dec;
6940
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 val = (char *)dec->val_decimal(nullptr);
6941 7 val_len = sizeof(my_decimal);
6942 7 break;
6943 }
6944 4707 case STRING_RESULT:
6945
2/4
✓ Branch 0 taken 4707 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4707 times.
✗ Branch 3 not taken.
4707 it = new Item_string(val, val_len, charset);
6946 4707 break;
6947 case ROW_RESULT:
6948 default:
6949 assert(false);
6950 return 0;
6951 }
6952 }
6953 Item_func_set_user_var *e =
6954
3/6
✓ Branch 0 taken 6744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6744 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6744 times.
✗ Branch 5 not taken.
6744 new Item_func_set_user_var(Name_string(name, name_len, false), it);
6955 /*
6956 Item_func_set_user_var can't substitute something else on its place =>
6957 0 can be passed as last argument (reference on item)
6958
6959 Fix_fields() can fail, in which case a call of update_hash() might
6960 crash the server, so if fix fields fails, we just return with an
6961 error.
6962 */
6963
2/4
✓ Branch 0 taken 6744 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6744 times.
6744 if (e->fix_fields(thd, nullptr)) return 1;
6964
6965
2/4
✓ Branch 0 taken 6744 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6744 times.
6744 if (e->set_entry(thd, true)) return 1;
6966
6967 /*
6968 A variable can just be considered as a table with
6969 a single record and with a single column. Thus, like
6970 a column value, it could always have IMPLICIT derivation.
6971 */
6972 6744 e->update_hash(val, val_len, (Item_result)type, charset, DERIVATION_IMPLICIT,
6973
1/2
✓ Branch 0 taken 6744 times.
✗ Branch 1 not taken.
6744 (flags & binary_log::User_var_event::UNSIGNED_F));
6974
1/2
✓ Branch 0 taken 6744 times.
✗ Branch 1 not taken.
6744 if (!is_deferred())
6975
1/2
✓ Branch 0 taken 6744 times.
✗ Branch 1 not taken.
6744 thd->mem_root->Clear();
6976 else
6977 current_thd->query_id = sav_query_id; /* restore current query's context */
6978
6979 6744 return 0;
6980 6745 }
6981
6982 3 int User_var_log_event::do_update_pos(Relay_log_info *rli) {
6983 3 rli->inc_event_relay_log_pos();
6984 3 return 0;
6985 }
6986
6987 6743 Log_event::enum_skip_reason User_var_log_event::do_shall_skip(
6988 Relay_log_info *rli) {
6989 /*
6990 It is a common error to set the slave skip counter to 1 instead
6991 of 2 when recovering from an insert which used a auto increment,
6992 rand, or user var. Therefore, if the slave skip counter is 1, we
6993 just say that this event should be skipped by ignoring it, meaning
6994 that we do not change the value of the slave skip counter since it
6995 will be decreased by the following insert event.
6996 */
6997 6743 return continue_group(rli);
6998 }
6999 #endif /* MYSQL_SERVER */
7000
7001 /**************************************************************************
7002 Unknown_log_event methods
7003 **************************************************************************/
7004
7005 #ifndef MYSQL_SERVER
7006 69 void Unknown_log_event::print(FILE *,
7007 PRINT_EVENT_INFO *print_event_info) const {
7008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (print_event_info->short_form) return;
7009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (what != kind::ENCRYPTED_WITH_5_7) {
7010 print_header(&print_event_info->head_cache, print_event_info, false);
7011 my_b_printf(&print_event_info->head_cache, "\n# %s", "Unknown event\n");
7012 } else
7013 69 my_b_printf(&print_event_info->head_cache, "\n# %s",
7014 "Event encrypted with 5.7 Percona Server binlog encryption\n");
7015 }
7016
7017 /**************************************************************************
7018 Stop_log_event methods
7019 **************************************************************************/
7020
7021 /*
7022 Stop_log_event::print()
7023 */
7024
7025 11 void Stop_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
7026
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
11 if (print_event_info->short_form) return;
7027
7028 6 print_header(&print_event_info->head_cache, print_event_info, false);
7029 6 my_b_printf(&print_event_info->head_cache, "\tStop\n");
7030 }
7031 #endif /* !MYSQL_SERVER */
7032
7033 #ifdef MYSQL_SERVER
7034 /*
7035 The master stopped. We used to clean up all temporary tables but
7036 this is useless as, as the master has shut down properly, it has
7037 written all DROP TEMPORARY TABLE (prepared statements' deletion is
7038 TODO only when we binlog prep stmts). We used to clean up
7039 replica_load_tmpdir, but this is useless as it has been cleared at the
7040 end of LOAD DATA INFILE. So we have nothing to do here. The place
7041 were we must do this cleaning is in
7042 Start_log_event_v3::do_apply_event(), not here. Because if we come
7043 here, the master was sane.
7044
7045 This must only be called from the Slave SQL thread, since it calls
7046 flush_relay_log_info().
7047 */
7048 1107 int Stop_log_event::do_update_pos(Relay_log_info *rli) {
7049 1107 int error_inc = 0;
7050 1107 int error_flush = 0;
7051 /*
7052 We do not want to update master_log pos because we get a rotate event
7053 before stop, so by now group_master_log_name is set to the next log.
7054 If we updated it, we will have incorrect master coordinates and this
7055 could give false triggers in SOURCE_POS_WAIT() that we have reached
7056 the target position when in fact we have not.
7057 The group position is always unchanged in MTS mode because the event
7058 is never executed so can't be scheduled to a Worker.
7059 */
7060
5/6
✓ Branch 0 taken 1107 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1103 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1103 times.
✓ Branch 5 taken 4 times.
1107 if ((thd->variables.option_bits & OPTION_BEGIN) || rli->is_parallel_exec())
7061 1103 rli->inc_event_relay_log_pos();
7062 else {
7063 4 error_inc = rli->inc_group_relay_log_pos(0, true /*need_data_lock=true*/);
7064 4 error_flush = rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT);
7065 }
7066
2/4
✓ Branch 0 taken 1107 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1107 times.
1107 return (error_inc || error_flush);
7067 }
7068
7069 /**************************************************************************
7070 Append_block_log_event methods
7071 **************************************************************************/
7072
7073 /*
7074 Append_block_log_event ctor
7075 */
7076
7077 8364 Append_block_log_event::Append_block_log_event(THD *thd_arg, const char *db_arg,
7078 uchar *block_arg,
7079 uint block_len_arg,
7080 98 bool using_trans)
7081 : binary_log::Append_block_event(db_arg, block_arg, block_len_arg,
7082 thd_arg->file_id),
7083 Log_event(thd_arg, 0,
7084 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
7085 : Log_event::EVENT_STMT_CACHE,
7086
3/5
✓ Branch 0 taken 3604 times.
✓ Branch 1 taken 578 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✗ Branch 4 not taken.
8364 Log_event::EVENT_NORMAL_LOGGING, header(), footer()) {
7087 8364 common_header->set_is_valid(block != nullptr);
7088 8364 }
7089 #endif // MYSQL_SERVER
7090
7091 /*
7092 Append_block_log_event ctor
7093 */
7094
7095 396 Append_block_log_event::Append_block_log_event(
7096 16 const char *buf, const Format_description_event *description_event)
7097 : binary_log::Append_block_event(buf, description_event),
7098
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
396 Log_event(header(), footer()) {
7099
1/2
✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
396 DBUG_TRACE;
7100 396 }
7101
7102 /*
7103 Append_block_log_event::write()
7104 */
7105
7106 #ifdef MYSQL_SERVER
7107 235 bool Append_block_log_event::write(Basic_ostream *ostream) {
7108 uchar buf[Binary_log_event::APPEND_BLOCK_HEADER_LEN];
7109 235 int4store(buf + AB_FILE_ID_OFFSET, file_id);
7110 470 return (write_header(ostream,
7111
1/2
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
235 Binary_log_event::APPEND_BLOCK_HEADER_LEN + block_len) ||
7112
2/4
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
✗ Branch 3 not taken.
235 wrapper_my_b_safe_write(ostream, buf,
7113 235 Binary_log_event::APPEND_BLOCK_HEADER_LEN) ||
7114
3/6
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 235 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 235 times.
✗ Branch 5 not taken.
705 wrapper_my_b_safe_write(ostream, block, block_len) ||
7115
2/4
✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 235 times.
470 write_footer(ostream));
7116 }
7117 #endif
7118
7119 /*
7120 Append_block_log_event::print()
7121 */
7122
7123 #ifndef MYSQL_SERVER
7124 50 void Append_block_log_event::print(FILE *,
7125 PRINT_EVENT_INFO *print_event_info) const {
7126
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 23 times.
50 if (print_event_info->short_form) return;
7127 23 print_header(&print_event_info->head_cache, print_event_info, false);
7128 23 my_b_printf(&print_event_info->head_cache,
7129 23 "\n#%s: file_id: %d block_len: %d\n", get_type_str(), file_id,
7130 23 block_len);
7131 }
7132 #endif /* !MYSQL_SERVER */
7133
7134 /*
7135 Append_block_log_event::pack_info()
7136 */
7137
7138 #if defined(MYSQL_SERVER)
7139 21 int Append_block_log_event::pack_info(Protocol *protocol) {
7140 char buf[256];
7141 size_t length;
7142 21 length = snprintf(buf, sizeof(buf), ";file_id=%u;block_len=%u", file_id,
7143 block_len);
7144
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 protocol->store_string(buf, length, &my_charset_bin);
7145 21 return 0;
7146 }
7147
7148 /*
7149 Append_block_log_event::get_create_or_append()
7150 */
7151
7152 4 int Append_block_log_event::get_create_or_append() const {
7153 4 return 0; /* append to the file, fail if not exists */
7154 }
7155
7156 /*
7157 Append_block_log_event::do_apply_event()
7158 */
7159
7160 102 int Append_block_log_event::do_apply_event(Relay_log_info const *rli) {
7161 char fname[FN_REFLEN + TEMP_FILE_MAX_LEN];
7162 int fd;
7163 102 int error = 1;
7164
1/2
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
102 DBUG_TRACE;
7165
7166
1/2
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
102 Applier_security_context_guard security_context{rli, thd};
7167
3/4
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
✓ Branch 3 taken 2 times.
102 if (DBUG_EVALUATE_IF("skip_the_priv_check_in_begin_load", false, true)) {
7168
3/4
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 94 times.
100 if (!security_context.skip_priv_checks()) {
7169
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
6 if (!security_context.has_access({FILE_ACL})) {
7170
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 rli->report_privilege_check_error(
7171 ERROR_LEVEL,
7172 Relay_log_info::enum_priv_checks_status::
7173 LOAD_DATA_EVENT_NOT_ALLOWED,
7174 false /* to client */);
7175 2 return ER_FILE_PRIVILEGE_FOR_REPLICATION_CHECKS;
7176 }
7177 }
7178 }
7179 #ifndef NDEBUG
7180 else { // Let's ensure that we actually skipped the privilege check since the
7181 // error code caugth in test scripts would be the same as the no-skip
7182 // case. Test scripts should wait on the below signal, if
7183 // `skip_the_priv_check_in_begin_load` has been set.
7184 2 const char act[] = "now SIGNAL skipped_the_priv_check_in_begin_load";
7185
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
7186 }
7187 #endif
7188
7189
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 THD_STAGE_INFO(thd, stage_making_temp_file_append_before_load_data);
7190
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 slave_load_file_stem(fname, file_id, server_id, ".data");
7191
3/4
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 4 times.
100 if (get_create_or_append()) {
7192 /*
7193 Usually lex_start() is called by dispatch_sql_command(), but we need it
7194 here as the present method does not call mysql_parse().
7195 */
7196
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 lex_start(thd);
7197
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 mysql_reset_thd_for_next_command(thd);
7198 /* old copy may exist already */
7199
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 mysql_file_delete(key_file_log_event_data, fname, MYF(0));
7200
2/4
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 96 times.
96 DBUG_EXECUTE_IF("simulate_file_create_error_Append_block_event",
7201 { strcat(fname, "/"); });
7202
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if ((fd = mysql_file_create(key_file_log_event_data, fname, CREATE_MODE,
7203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 O_WRONLY | O_EXCL | O_NOFOLLOW, MYF(MY_WME))) <
7204 0) {
7205 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
7206 "Error in %s event: could not create file '%s', '%s'",
7207 get_type_str(), fname, thd->get_stmt_da()->message_text());
7208 goto err;
7209 }
7210
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 } else if ((fd = mysql_file_open(key_file_log_event_data, fname,
7211 O_WRONLY | O_APPEND | O_NOFOLLOW,
7212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 MYF(MY_WME))) < 0) {
7213 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
7214 "Error in %s event: could not open file '%s', '%s'",
7215 get_type_str(), fname, thd->get_stmt_da()->message_text());
7216 goto err;
7217 }
7218
4/6
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 99 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
100 DBUG_EXECUTE_IF("remove_replica_load_file_before_write",
7219 { my_delete_allow_opened(fname, MYF(0)); });
7220
7221
2/6
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 100 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
100 DBUG_EXECUTE_IF("simulate_file_write_error_Append_block_event",
7222 { mysql_file_close(fd, MYF(0)); });
7223
2/4
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 100 times.
100 if (mysql_file_write(fd, block, block_len, MYF(MY_WME + MY_NABP))) {
7224 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
7225 "Error in %s event: write to '%s' failed, '%s'", get_type_str(),
7226 fname, thd->get_stmt_da()->message_text());
7227 goto err;
7228 }
7229 100 error = 0;
7230
7231 100 err:
7232
2/4
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
100 if (fd >= 0) mysql_file_close(fd, MYF(0));
7233 100 return error;
7234 102 }
7235
7236 /**************************************************************************
7237 Delete_file_log_event methods
7238 **************************************************************************/
7239
7240 /*
7241 Delete_file_log_event ctor
7242 */
7243
7244 11 Delete_file_log_event::Delete_file_log_event(THD *thd_arg, const char *db_arg,
7245 11 bool using_trans)
7246 : binary_log::Delete_file_event(thd_arg->file_id, db_arg),
7247 Log_event(thd_arg, 0,
7248 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
7249 : Log_event::EVENT_STMT_CACHE,
7250
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 Log_event::EVENT_NORMAL_LOGGING, header(), footer()) {
7251 11 common_header->set_is_valid(file_id != 0);
7252 11 }
7253 #endif // MYSQL_SERVER
7254
7255 /*
7256 Delete_file_log_event ctor
7257 */
7258
7259 5 Delete_file_log_event::Delete_file_log_event(
7260 5 const char *buf, const Format_description_event *description_event)
7261 : binary_log::Delete_file_event(buf, description_event),
7262
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 Log_event(header(), footer()) {
7263
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 DBUG_TRACE;
7264 5 }
7265
7266 /*
7267 Delete_file_log_event::write()
7268 */
7269
7270 #ifdef MYSQL_SERVER
7271 11 bool Delete_file_log_event::write(Basic_ostream *ostream) {
7272 uchar buf[Binary_log_event::DELETE_FILE_HEADER_LEN];
7273 11 int4store(buf + DF_FILE_ID_OFFSET, file_id);
7274
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 return (write_header(ostream, sizeof(buf)) ||
7275
3/6
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
22 wrapper_my_b_safe_write(ostream, buf, sizeof(buf)) ||
7276
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
22 write_footer(ostream));
7277 }
7278 #endif
7279
7280 /*
7281 Delete_file_log_event::print()
7282 */
7283
7284 #ifndef MYSQL_SERVER
7285 void Delete_file_log_event::print(FILE *,
7286 PRINT_EVENT_INFO *print_event_info) const {
7287 if (print_event_info->short_form) return;
7288 print_header(&print_event_info->head_cache, print_event_info, false);
7289 my_b_printf(&print_event_info->head_cache, "\n#Delete_file: file_id=%u\n",
7290 file_id);
7291 }
7292 #endif /* !MYSQL_SERVER */
7293
7294 /*
7295 Delete_file_log_event::pack_info()
7296 */
7297
7298 #if defined(MYSQL_SERVER)
7299 int Delete_file_log_event::pack_info(Protocol *protocol) {
7300 char buf[64];
7301 size_t length;
7302 length = snprintf(buf, sizeof(buf), ";file_id=%u", (uint)file_id);
7303 protocol->store_string(buf, length, &my_charset_bin);
7304 return 0;
7305 }
7306
7307 /*
7308 Delete_file_log_event::do_apply_event()
7309 */
7310
7311 4 int Delete_file_log_event::do_apply_event(Relay_log_info const *rli) {
7312 char fname[FN_REFLEN + TEMP_FILE_MAX_LEN];
7313
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 lex_start(thd);
7314
7315
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 Applier_security_context_guard security_context{rli, thd};
7316
3/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
4 if (!security_context.skip_priv_checks()) {
7317
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 if (!security_context.has_access({FILE_ACL})) {
7318
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report_privilege_check_error(
7319 ERROR_LEVEL,
7320 Relay_log_info::enum_priv_checks_status::LOAD_DATA_EVENT_NOT_ALLOWED,
7321 false /* to client */);
7322 1 return ER_FILE_PRIVILEGE_FOR_REPLICATION_CHECKS;
7323 }
7324 }
7325
7326
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mysql_reset_thd_for_next_command(thd);
7327
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 char *ext = slave_load_file_stem(fname, file_id, server_id, ".data");
7328
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME));
7329 3 my_stpcpy(ext, ".info");
7330
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mysql_file_delete(key_file_log_event_info, fname, MYF(MY_WME));
7331 3 return 0;
7332 4 }
7333
7334 /**************************************************************************
7335 Begin_load_query_log_event methods
7336 **************************************************************************/
7337
7338 8266 Begin_load_query_log_event::Begin_load_query_log_event(THD *thd_arg,
7339 const char *db_arg,
7340 uchar *block_arg,
7341 uint block_len_arg,
7342 8266 bool using_trans)
7343 : binary_log::Append_block_event(db_arg, block_arg, block_len_arg,
7344 thd_arg->file_id),
7345 Append_block_log_event(thd_arg, db_arg, block_arg, block_len_arg,
7346 using_trans),
7347
1/2
✓ Branch 0 taken 4133 times.
✗ Branch 1 not taken.
8266 binary_log::Begin_load_query_event() {
7348 8266 common_header->type_code = binary_log::BEGIN_LOAD_QUERY_EVENT;
7349
1/2
✓ Branch 0 taken 4133 times.
✗ Branch 1 not taken.
8266 file_id = thd_arg->file_id = mysql_bin_log.next_file_id();
7350 }
7351 #endif // MYSQL_SERVER
7352
7353 380 Begin_load_query_log_event::Begin_load_query_log_event(
7354 380 const char *buf, const Format_description_event *desc_event)
7355 : binary_log::Append_block_event(buf, desc_event),
7356 Append_block_log_event(buf, desc_event),
7357
2/4
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 190 times.
✗ Branch 3 not taken.
380 binary_log::Begin_load_query_event(buf, desc_event) {
7358
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
380 DBUG_TRACE;
7359 }
7360
7361 #if defined(MYSQL_SERVER)
7362 96 int Begin_load_query_log_event::get_create_or_append() const {
7363 96 return 1; /* create the file */
7364 }
7365
7366 104 Log_event::enum_skip_reason Begin_load_query_log_event::do_shall_skip(
7367 Relay_log_info *rli) {
7368 /*
7369 If the slave skip counter is 1, then we should not start executing
7370 on the next event.
7371 */
7372 104 return continue_group(rli);
7373 }
7374
7375 /**************************************************************************
7376 Execute_load_query_log_event methods
7377 **************************************************************************/
7378
7379 8244 Execute_load_query_log_event::Execute_load_query_log_event(
7380 THD *thd_arg, const char *query_arg, ulong query_length_arg,
7381 uint fn_pos_start_arg, uint fn_pos_end_arg,
7382 binary_log::enum_load_dup_handling dup_handling_arg, bool using_trans,
7383 8244 bool immediate, bool suppress_use, int errcode)
7384 : binary_log::Query_event(
7385 8244 query_arg, thd_arg->catalog().str, thd_arg->db().str,
7386 8244 query_length_arg, thd_arg->thread_id(), thd_arg->variables.sql_mode,
7387 thd_arg->variables.auto_increment_increment,
7388 thd_arg->variables.auto_increment_offset,
7389 8244 thd_arg->variables.lc_time_names->number,
7390 8244 (ulonglong)thd_arg->table_map_for_update, errcode),
7391 Query_log_event(thd_arg, query_arg, query_length_arg, using_trans,
7392 immediate, suppress_use, errcode),
7393 binary_log::Execute_load_query_event(thd_arg->file_id, fn_pos_start_arg,
7394
2/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 4122 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4122 times.
✗ Branch 5 not taken.
16488 fn_pos_end_arg, dup_handling_arg) {
7395
3/6
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4122 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4122 times.
✗ Branch 5 not taken.
8244 common_header->set_is_valid(Query_log_event::is_valid() && file_id != 0);
7396 8244 common_header->type_code = binary_log::EXECUTE_LOAD_QUERY_EVENT;
7397 }
7398 #endif /* MYSQL_SERVER */
7399
7400 364 Execute_load_query_log_event::Execute_load_query_log_event(
7401 364 const char *buf, const Format_description_event *desc_event)
7402 : binary_log::Query_event(buf, desc_event,
7403 binary_log::EXECUTE_LOAD_QUERY_EVENT),
7404 Query_log_event(buf, desc_event, binary_log::EXECUTE_LOAD_QUERY_EVENT),
7405
2/4
✓ Branch 0 taken 182 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182 times.
✗ Branch 3 not taken.
364 binary_log::Execute_load_query_event(buf, desc_event) {
7406
1/2
✓ Branch 0 taken 182 times.
✗ Branch 1 not taken.
364 DBUG_TRACE;
7407
3/4
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 134 times.
364 if (!is_valid()) return;
7408
3/4
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 134 times.
364 if (!Query_log_event::is_valid()) {
7409 // clear all the variables set in execute_load_query_event
7410 file_id = 0;
7411 fn_pos_start = 0;
7412 fn_pos_end = 0;
7413 dup_handling = binary_log::LOAD_DUP_ERROR;
7414 }
7415
3/6
✓ Branch 0 taken 182 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 134 times.
✗ Branch 5 not taken.
364 common_header->set_is_valid(Query_log_event::is_valid() && file_id != 0);
7416 }
7417
7418 217 ulong Execute_load_query_log_event::get_post_header_size_for_derived() {
7419 217 return Binary_log_event::EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN;
7420 }
7421
7422 #ifdef MYSQL_SERVER
7423 217 bool Execute_load_query_log_event::write_post_header_for_derived(
7424 Basic_ostream *ostream) {
7425 uchar buf[Binary_log_event::EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN];
7426 217 int4store(buf, file_id);
7427 217 int4store(buf + 4, fn_pos_start);
7428 217 int4store(buf + 4 + 4, fn_pos_end);
7429 217 *(buf + 4 + 4 + 4) = (uchar)dup_handling;
7430
7431
1/2
✓ Branch 0 taken 217 times.
✗ Branch 1 not taken.
217 return wrapper_my_b_safe_write(
7432 434 ostream, buf, Binary_log_event::EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN);
7433 }
7434 #endif
7435
7436 #ifndef MYSQL_SERVER
7437 void Execute_load_query_log_event::print(
7438 FILE *file, PRINT_EVENT_INFO *print_event_info) const {
7439 print(file, print_event_info, nullptr);
7440 }
7441
7442 /**
7443 Prints the query as LOAD DATA LOCAL and with rewritten filename.
7444 */
7445 36 void Execute_load_query_log_event::print(FILE *,
7446 PRINT_EVENT_INFO *print_event_info,
7447 const char *local_fname) const {
7448 [[maybe_unused]] int write_res;
7449 36 IO_CACHE *const head = &print_event_info->head_cache;
7450
7451 36 print_query_header(head, print_event_info);
7452 /**
7453 reduce the size of io cache so that the write function is called
7454 for every call to my_b_printf().
7455 */
7456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 DBUG_EXECUTE_IF("simulate_execute_event_write_error", {
7457 head->write_pos = head->write_end;
7458 DBUG_SET("+d,simulate_file_write_error");
7459 });
7460
7461
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 if (local_fname) {
7462 write_res =
7463 36 my_b_write(head, pointer_cast<const uchar *>(query), fn_pos_start);
7464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 assert(write_res == 0);
7465 36 my_b_printf(head, " LOCAL INFILE ");
7466 36 pretty_print_str(head, local_fname, strlen(local_fname));
7467
7468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (dup_handling == binary_log::LOAD_DUP_REPLACE)
7469 my_b_printf(head, " REPLACE");
7470 36 my_b_printf(head, " INTO");
7471 36 my_b_write(head, pointer_cast<const uchar *>(query) + fn_pos_end,
7472 36 q_len - fn_pos_end);
7473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 assert(write_res == 0);
7474 36 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
7475 } else {
7476 write_res = my_b_write(head, pointer_cast<const uchar *>(query), q_len);
7477 assert(write_res == 0);
7478 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
7479 }
7480
7481
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 21 times.
36 if (!print_event_info->short_form)
7482 15 my_b_printf(head, "# file_id: %d \n", file_id);
7483 36 }
7484 #endif
7485
7486 #if defined(MYSQL_SERVER)
7487 19 int Execute_load_query_log_event::pack_info(Protocol *protocol) {
7488 char *buf, *pos;
7489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!(buf = (char *)my_malloc(key_memory_log_event,
7490 19 9 + (db_len * 2) + 2 + q_len + 10 + 21,
7491 MYF(MY_WME))))
7492 return 1;
7493 19 pos = buf;
7494
2/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
19 if (db && db_len) {
7495 /*
7496 Statically allocates room to store '\0' and an identifier
7497 that may have NAME_LEN * 2 due to quoting and there are
7498 two quoting characters that wrap them.
7499 */
7500 char quoted_db[1 + NAME_LEN * 2 + 2]; // quoted length of the identifier
7501 19 size_t size = 0;
7502
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 size = my_strmov_quoted_identifier(this->thd, quoted_db, db, 0);
7503 19 pos = my_stpcpy(buf, "use ");
7504 19 memcpy(pos, quoted_db, size);
7505 19 pos = my_stpcpy(pos + size, "; ");
7506 }
7507
2/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
19 if (query && q_len) {
7508 19 memcpy(pos, query, q_len);
7509 19 pos += q_len;
7510 }
7511 19 pos = my_stpcpy(pos, " ;file_id=");
7512 19 pos = longlong10_to_str(file_id, pos, 10);
7513 19 protocol->store_string(buf, pos - buf, &my_charset_bin);
7514 19 my_free(buf);
7515 19 return 0;
7516 }
7517
7518 92 int Execute_load_query_log_event::do_apply_event(Relay_log_info const *rli) {
7519 char *p;
7520 char *buf;
7521 char *fname;
7522 char *fname_end;
7523 int error;
7524
7525
1/2
✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
92 Applier_security_context_guard security_context{rli, thd};
7526
3/4
✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 89 times.
92 if (!security_context.skip_priv_checks()) {
7527
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 if (!security_context.has_access({FILE_ACL})) {
7528
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report_privilege_check_error(
7529 ERROR_LEVEL,
7530 Relay_log_info::enum_priv_checks_status::LOAD_DATA_EVENT_NOT_ALLOWED,
7531 false /* to client */);
7532 1 return ER_FILE_PRIVILEGE_FOR_REPLICATION_CHECKS;
7533 }
7534 }
7535
7536 182 buf = (char *)my_malloc(key_memory_log_event,
7537
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 q_len + 1 - (fn_pos_end - fn_pos_start) +
7538 (FN_REFLEN + TEMP_FILE_MAX_LEN) + 10 + 8 + 5,
7539 MYF(MY_WME));
7540
7541
4/6
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 90 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
91 DBUG_EXECUTE_IF("LOAD_DATA_INFILE_has_fatal_error", my_free(buf);
7542 buf = nullptr;);
7543
7544 /* Replace filename and LOCAL keyword in query before executing it */
7545
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 90 times.
91 if (buf == nullptr) {
7546
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
7547
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ER_THD(thd, ER_SLAVE_FATAL_ERROR), "Not enough memory");
7548 1 return 1;
7549 }
7550
7551 90 p = buf;
7552 90 memcpy(p, query, fn_pos_start);
7553 90 p += fn_pos_start;
7554
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 fname = (p = strmake(p, STRING_WITH_LEN(" INFILE \'")));
7555
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 p = slave_load_file_stem(p, file_id, server_id, ".data");
7556 90 fname_end = p = strend(p); // Safer than p=p+5
7557 90 *(p++) = '\'';
7558
3/3
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 51 times.
90 switch (dup_handling) {
7559 35 case binary_log::LOAD_DUP_IGNORE:
7560
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 p = strmake(p, STRING_WITH_LEN(" IGNORE"));
7561 35 break;
7562 4 case binary_log::LOAD_DUP_REPLACE:
7563
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 p = strmake(p, STRING_WITH_LEN(" REPLACE"));
7564 4 break;
7565 51 default:
7566 /* Ordinary load data */
7567 51 break;
7568 }
7569
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 p = strmake(p, STRING_WITH_LEN(" INTO "));
7570
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 p = strmake(p, query + fn_pos_end, q_len - fn_pos_end);
7571
7572
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 error = Query_log_event::do_apply_event(rli, buf, p - buf);
7573
7574 /* Forging file name for deletion in same buffer */
7575 90 *fname_end = 0;
7576
7577 /*
7578 If there was an error the slave is going to stop, leave the
7579 file so that we can re-execute this event at START SLAVE.
7580 */
7581
3/4
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
90 if (!error) mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME));
7582
7583
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 my_free(buf);
7584 90 return error;
7585 92 }
7586
7587 /*****************************************************************************
7588 Load_query_generator is used to generate the LOAD DATA statement for binlog
7589 ******************************************************************************/
7590
7591 4122 Load_query_generator::Load_query_generator(THD *thd_arg, const sql_exchange *ex,
7592 const char *db_arg,
7593 const char *table_name_arg,
7594 bool is_concurrent_arg, bool replace,
7595 4122 bool ignore)
7596 4122 : str((char *)buf, BUF_SIZE, &my_charset_bin),
7597 4122 thd(thd_arg),
7598 4122 sql_ex(ex),
7599 4122 db(db_arg),
7600
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 table_name(table_name_arg ? table_name_arg : ""),
7601 4122 fname(ex->file_name),
7602 4122 is_concurrent(is_concurrent_arg),
7603 4122 has_replace(replace),
7604 4122 has_ignore(ignore) {
7605 4122 str.length(0);
7606 4122 }
7607
7608 4122 const String *Load_query_generator::generate(size_t *fn_start, size_t *fn_end) {
7609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4122 times.
4122 assert(thd->lex->sql_command == SQLCOM_LOAD);
7610 4122 auto cmd = down_cast<Sql_cmd_load_table *>(thd->lex->m_sql_cmd);
7611
7612
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 str.append("LOAD DATA ");
7613
7614
3/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4102 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
4122 if (is_concurrent) str.append("CONCURRENT ");
7615
7616
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 if (fn_start) *fn_start = str.length() - 1;
7617
7618
3/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 4077 times.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
4122 if (cmd->m_is_local_file) str.append("LOCAL ");
7619
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 str.append("INFILE ");
7620 4122 pretty_print_str(&str, fname, strlen(fname));
7621
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 str.append(" ");
7622
7623
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4114 times.
4122 if (has_replace)
7624
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 str.append("REPLACE ");
7625
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 4028 times.
4114 else if (has_ignore)
7626
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 str.append("IGNORE ");
7627
7628
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 str.append("INTO");
7629
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 if (fn_end) *fn_end = str.length();
7630
7631
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 str.append(" TABLE ");
7632
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 str.append(table_name);
7633
7634
2/2
✓ Branch 0 taken 1304 times.
✓ Branch 1 taken 2818 times.
4122 if (sql_ex->cs != nullptr) {
7635
1/2
✓ Branch 0 taken 1304 times.
✗ Branch 1 not taken.
1304 str.append(" CHARACTER SET ");
7636
1/2
✓ Branch 0 taken 1304 times.
✗ Branch 1 not taken.
1304 str.append(sql_ex->cs->csname);
7637 }
7638
7639 /* We have to create all optional fields as the default is not empty */
7640
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 str.append(" FIELDS TERMINATED BY ");
7641 4122 pretty_print_str(&str, sql_ex->field.field_term);
7642
7643
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4110 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
4122 if (sql_ex->field.opt_enclosed) str.append(" OPTIONALLY ");
7644
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 str.append(" ENCLOSED BY ");
7645 4122 pretty_print_str(&str, sql_ex->field.enclosed);
7646
7647
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 str.append(" ESCAPED BY ");
7648 4122 pretty_print_str(&str, sql_ex->field.escaped);
7649
7650
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 str.append(" LINES TERMINATED BY ");
7651 4122 pretty_print_str(&str, sql_ex->line.line_term);
7652
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4106 times.
4122 if (sql_ex->line.line_start->length() > 0) {
7653
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 str.append(" STARTING BY ");
7654 16 pretty_print_str(&str, sql_ex->line.line_start);
7655 }
7656
7657
2/2
✓ Branch 0 taken 1319 times.
✓ Branch 1 taken 2803 times.
4122 if (sql_ex->skip_lines > 0) {
7658
1/2
✓ Branch 0 taken 1319 times.
✗ Branch 1 not taken.
1319 str.append(" IGNORE ");
7659 1319 str.append_ulonglong(sql_ex->skip_lines);
7660
1/2
✓ Branch 0 taken 1319 times.
✗ Branch 1 not taken.
1319 str.append(" LINES ");
7661 }
7662
7663 /* prepare fields-list */
7664
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 if (!cmd->m_opt_fields_or_vars.empty()) {
7665
1/2
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
4122 str.append(" (");
7666
7667
6/10
✓ Branch 0 taken 4122 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4122 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4242 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8364 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4242 times.
✓ Branch 9 taken 4122 times.
8364 for (Item *item : cmd->m_opt_fields_or_vars) {
7668
7/10
✓ Branch 0 taken 4242 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 4230 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✓ Branch 8 taken 4230 times.
✓ Branch 9 taken 12 times.
4242 if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM)
7669
1/2
✓ Branch 0 taken 4230 times.
✗ Branch 1 not taken.
4230 append_identifier(thd, &str, item->item_name.ptr(),
7670 strlen(item->item_name.ptr()));
7671 else
7672
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 item->print(thd, &str, QT_ORDINARY);
7673
2/4
✓ Branch 0 taken 4242 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4242 times.
✗ Branch 3 not taken.
4242 str.append(", ");
7674 }
7675 // remove the last ", "
7676 4122 str.length(str.length() - 2);
7677 4122 str.append(')');
7678 }
7679
7680
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4108 times.
4122 if (!cmd->m_opt_set_fields.empty()) {
7681
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 List_iterator<String> ls(*cmd->m_opt_set_expr_strings);
7682
7683
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 str.append(" SET ");
7684
7685
6/10
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16 times.
✓ Branch 9 taken 14 times.
30 for (Item *item : cmd->m_opt_set_fields) {
7686 16 String *s = ls++;
7687
7688
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 append_identifier(thd, &str, item->item_name.ptr(),
7689 strlen(item->item_name.ptr()));
7690
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 str.append(*s);
7691
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 str.append(", ");
7692 }
7693 // remove the last ", "
7694 14 str.length(str.length() - 2);
7695 }
7696
7697 4122 return &str;
7698 }
7699
7700 #endif // MYSQL_SERVER
7701 #ifndef NDEBUG
7702 #ifdef MYSQL_SERVER
7703 static uchar dbug_extra_row_ndb_info_val = 0;
7704 static int dbug_extra_row_ndb_info_val_limit = 0;
7705
7706 /**
7707 set_extra_data
7708
7709 Called during self-test to generate various
7710 self-consistent binlog row event extra
7711 thread data structures which can be checked
7712 when reading the binlog.
7713
7714 @note if you are using this debug point, find the number of times this
7715 method is used for your test and then use that value for the reset_limit
7716 parameter in order to avoid inter test contamination.
7717
7718 @param arr Buffer to use
7719 @param reset_limit the limit upon which the counters reset
7720 */
7721 623 static const uchar *set_extra_data(uchar *arr, int reset_limit) {
7722 623 uchar val = (dbug_extra_row_ndb_info_val++) %
7723 623 (EXTRA_ROW_INFO_MAX_PAYLOAD + 1); /* 0 .. MAX_PAYLOAD + 1 */
7724 623 arr[EXTRA_ROW_INFO_LEN_OFFSET] = val + EXTRA_ROW_INFO_HEADER_LENGTH;
7725 623 arr[EXTRA_ROW_INFO_FORMAT_OFFSET] = val;
7726
2/2
✓ Branch 0 taken 69833 times.
✓ Branch 1 taken 623 times.
70456 for (uchar i = 0; i < val; i++) arr[EXTRA_ROW_INFO_HEADER_LENGTH + i] = val;
7727
7728 623 dbug_extra_row_ndb_info_val_limit++;
7729
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 621 times.
623 if (dbug_extra_row_ndb_info_val_limit == reset_limit) {
7730 2 dbug_extra_row_ndb_info_val = 0;
7731 2 dbug_extra_row_ndb_info_val_limit = 0;
7732 }
7733
7734 623 return arr;
7735 }
7736
7737 #endif // #ifdef MYSQL_SERVER
7738
7739 /**
7740 check_extra_row_ndb_info
7741
7742 Called during self-test to check that
7743 binlog row event extra data is self-
7744 consistent as defined by the set_extra_data
7745 function above.
7746
7747 Will assert(false) if not.
7748 */
7749 623 static void check_extra_row_ndb_info(uchar *extra_row_ndb_info) {
7750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 623 times.
623 assert(extra_row_ndb_info);
7751 623 size_t len = extra_row_ndb_info[EXTRA_ROW_INFO_LEN_OFFSET];
7752 623 size_t val = len - EXTRA_ROW_INFO_HEADER_LENGTH;
7753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 623 times.
623 assert(extra_row_ndb_info[EXTRA_ROW_INFO_FORMAT_OFFSET] == val);
7754
2/2
✓ Branch 0 taken 69833 times.
✓ Branch 1 taken 623 times.
70456 for (size_t i = 0; i < val; i++) {
7755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69833 times.
69833 assert(extra_row_ndb_info[EXTRA_ROW_INFO_HEADER_LENGTH + i] == val);
7756 }
7757 623 }
7758
7759 #endif // #ifndef NDEBUG
7760
7761 121465833 int get_rpl_part_id(partition_info *part_info) {
7762 121465833 uint32_t part_id = binary_log::Rows_event::Extra_row_info::UNDEFINED;
7763 longlong func_value;
7764
2/2
✓ Branch 0 taken 33838363 times.
✓ Branch 1 taken 87627470 times.
121465833 if (part_info != nullptr) {
7765
1/2
✓ Branch 0 taken 33844466 times.
✗ Branch 1 not taken.
33838363 part_info->get_partition_id(part_info, &part_id, &func_value);
7766 }
7767 121471936 return static_cast<int>(part_id);
7768 }
7769
7770 /**************************************************************************
7771 Rows_log_event member functions
7772 **************************************************************************/
7773
7774 #ifdef MYSQL_SERVER
7775 52107360 Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg,
7776 const Table_id &tid, MY_BITMAP const *cols,
7777 bool using_trans, Log_event_type event_type,
7778 const unsigned char *extra_row_ndb_info)
7779 : binary_log::Rows_event(event_type),
7780 Log_event(thd_arg, 0,
7781 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
7782 : Log_event::EVENT_STMT_CACHE,
7783 Log_event::EVENT_NORMAL_LOGGING, header(), footer()),
7784 52107762 m_curr_row(nullptr),
7785 52107762 m_curr_row_end(nullptr),
7786 52107762 m_key(nullptr),
7787 52107762 m_key_info(nullptr),
7788
1/2
✓ Branch 0 taken 26053408 times.
✗ Branch 1 not taken.
52107762 m_distinct_keys(Key_compare(&m_key_info)),
7789 52107646 m_distinct_key_spare_buf(nullptr),
7790
4/6
✓ Branch 0 taken 25740118 times.
✓ Branch 1 taken 313665 times.
✓ Branch 2 taken 26053974 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26054034 times.
✗ Branch 5 not taken.
104215130 m_fields{tbl_arg, Replicated_columns_view::OUTBOUND} {
7791
1/2
✓ Branch 0 taken 26053951 times.
✗ Branch 1 not taken.
52108024 DBUG_TRACE;
7792 52107902 common_header->type_code = event_type;
7793 52107902 m_row_count = 0;
7794 52107902 m_table_id = tid;
7795
1/2
✓ Branch 0 taken 26053951 times.
✗ Branch 1 not taken.
52107902 m_width = tbl_arg ? this->m_fields.filtered_size() : 1;
7796 52107900 m_rows_buf = nullptr;
7797 52107900 m_rows_cur = nullptr;
7798 52107900 m_rows_end = nullptr;
7799 52107900 m_flags = 0;
7800 52107900 m_type = event_type;
7801
7802
4/6
✓ Branch 0 taken 26053955 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26053955 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26053926 times.
✓ Branch 5 taken 10 times.
52107900 assert(tbl_arg && tbl_arg->s && tid.is_valid());
7803
7804
2/2
✓ Branch 0 taken 1770 times.
✓ Branch 1 taken 26052156 times.
52107852 if (thd_arg->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS)
7805 3540 set_flags(NO_FOREIGN_KEY_CHECKS_F);
7806
2/2
✓ Branch 0 taken 1578 times.
✓ Branch 1 taken 26052348 times.
52107852 if (thd_arg->variables.option_bits & OPTION_RELAXED_UNIQUE_CHECKS)
7807 3156 set_flags(RELAXED_UNIQUE_CHECKS_F);
7808 #ifndef NDEBUG
7809 uchar extra_data[255];
7810
3/4
✓ Branch 0 taken 26053801 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 620 times.
✓ Branch 3 taken 26053181 times.
52107852 DBUG_EXECUTE_IF("extra_row_ndb_info_set_618",
7811 /* Set extra row data to a known value */
7812 extra_row_ndb_info = set_extra_data(extra_data, 618););
7813
3/4
✓ Branch 0 taken 26053875 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 26053872 times.
52107602 DBUG_EXECUTE_IF("extra_row_ndb_info_set_3",
7814 /* Set extra row data to a known value */
7815 extra_row_ndb_info = set_extra_data(extra_data, 3););
7816 #endif
7817 52107750 partition_info *part_info = tbl_arg->part_info;
7818
1/2
✓ Branch 0 taken 26053914 times.
✗ Branch 1 not taken.
52107750 auto part_id = get_rpl_part_id(part_info);
7819
2/2
✓ Branch 0 taken 15391897 times.
✓ Branch 1 taken 10662017 times.
52107828 if (part_id != binary_log::Rows_event::Extra_row_info::UNDEFINED) {
7820 30783794 m_extra_row_info.set_partition_id(part_id);
7821 }
7822 /* Copy Extra ndb data from thd into new event */
7823
2/2
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 26053291 times.
52107828 if (extra_row_ndb_info) {
7824 /* Copy Extra data from thd into new event */
7825 1246 int extra_row_ndb_info_len = extra_row_ndb_info[EXTRA_ROW_INFO_LEN_OFFSET];
7826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 623 times.
1246 assert(extra_row_ndb_info_len >= EXTRA_ROW_INFO_HEADER_LENGTH);
7827
7828
1/2
✓ Branch 0 taken 427 times.
✗ Branch 1 not taken.
1246 m_extra_row_info.set_ndb_info(extra_row_ndb_info, extra_row_ndb_info_len);
7829 }
7830
7831 /* if bitmap_init fails, caught in is_valid() */
7832
2/4
✓ Branch 0 taken 26053959 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26053923 times.
✗ Branch 3 not taken.
52107436 if (likely(!bitmap_init(&m_cols,
7833 52107436 m_width <= sizeof(m_bitbuf) * 8 ? m_bitbuf : nullptr,
7834
2/2
✓ Branch 0 taken 26052594 times.
✓ Branch 1 taken 1124 times.
52107436 m_width))) {
7835 /* Cols can be zero if this is a dummy binrows event */
7836
2/2
✓ Branch 0 taken 26053924 times.
✓ Branch 1 taken 18 times.
52107846 if (likely(cols != nullptr)) {
7837 // 'cols' may have additional hidden columns at the end.
7838
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26053924 times.
52107848 assert(cols->n_bits >= m_cols.n_bits);
7839
1/2
✓ Branch 0 taken 26053776 times.
✗ Branch 1 not taken.
52107848 bitmap_n_copy(&m_cols, cols);
7840 }
7841 } else {
7842 // Needed because bitmap_init() does not set it to null on failure
7843 m_cols.bitmap = nullptr;
7844 }
7845
7846
2/4
✓ Branch 0 taken 26053944 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26053944 times.
52107588 if (bitmap_init(&write_set_backup, nullptr, tbl_arg->s->fields)) {
7847 write_set_backup.bitmap = nullptr; /* purecov: deadcode */
7848 }
7849
7850 /*
7851 -Check that malloc() succeeded in allocating memory for the rows
7852 buffer and the COLS vector.
7853 -Checking that an Update_rows_log_event
7854 is valid is done while setting the Update_rows_log_event::is_valid
7855 */
7856
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 26053944 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
52107888 common_header->set_is_valid(m_rows_buf && m_cols.bitmap &&
7857 write_set_backup.bitmap);
7858 }
7859 #endif
7860
7861 46233434 Rows_log_event::Rows_log_event(
7862 const char *buf, const Format_description_event *description_event)
7863 : binary_log::Rows_event(buf, description_event),
7864 Log_event(header(), footer()),
7865 46233434 m_row_count(0),
7866 #ifdef MYSQL_SERVER
7867 46164318 m_table(nullptr),
7868 #endif
7869 46233434 m_rows_buf(nullptr),
7870 46233434 m_rows_cur(nullptr),
7871 46233434 m_rows_end(nullptr)
7872 #if defined(MYSQL_SERVER)
7873 ,
7874 46164318 m_curr_row(nullptr),
7875 46164318 m_curr_row_end(nullptr),
7876 46164318 m_key(nullptr),
7877 46164318 m_key_info(nullptr),
7878
1/2
✓ Branch 0 taken 23082159 times.
✗ Branch 1 not taken.
46164318 m_distinct_keys(Key_compare(&m_key_info)),
7879 46164318 m_distinct_key_spare_buf(nullptr),
7880
2/4
✓ Branch 0 taken 23082159 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23082159 times.
✗ Branch 3 not taken.
92328636 m_fields(Replicated_columns_view::INBOUND)
7881 #endif
7882 {
7883
1/2
✓ Branch 0 taken 23116717 times.
✗ Branch 1 not taken.
46233434 DBUG_TRACE;
7884
3/4
✓ Branch 0 taken 23082159 times.
✓ Branch 1 taken 34558 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23082159 times.
46233434 if (!is_valid()) return;
7885
7886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23116717 times.
46233434 assert(header()->type_code == m_type);
7887
7888
2/2
✓ Branch 0 taken 658 times.
✓ Branch 1 taken 23116059 times.
46233434 if (m_extra_row_info.have_ndb_info())
7889
3/4
✓ Branch 0 taken 658 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 623 times.
✓ Branch 3 taken 35 times.
1316 DBUG_EXECUTE_IF("extra_row_ndb_info_check",
7890 /* Check extra data has expected value */
7891 check_extra_row_ndb_info(m_extra_row_info.get_ndb_info()););
7892
7893 /*
7894 m_cols and m_cols_ai are of the type MY_BITMAP, which are members of
7895 class Rows_log_event, and are used while applying the row events on
7896 the slave.
7897 The bitmap integer is initialized by copying the contents of the
7898 vector column_before_image for m_cols.bitamp, and vector
7899 column_after_image for m_cols_ai.bitmap. m_cols_ai is only initialized
7900 for UPDATE_ROWS_EVENTS, else it is equal to the before image.
7901 */
7902 /* if bitmap_init fails, is_valid will be set to false */
7903
2/4
✓ Branch 0 taken 23116717 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23116717 times.
✗ Branch 3 not taken.
46233434 if (likely(!bitmap_init(&m_cols,
7904 46233434 m_width <= sizeof(m_bitbuf) * 8 ? m_bitbuf : nullptr,
7905
2/2
✓ Branch 0 taken 23115606 times.
✓ Branch 1 taken 1111 times.
46233434 m_width))) {
7906
1/2
✓ Branch 0 taken 23116717 times.
✗ Branch 1 not taken.
46233434 if (!columns_before_image.empty()) {
7907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23116717 times.
46233434 assert(n_bits_len == (m_width + 7) / 8);
7908 46233434 memcpy(m_cols.bitmap, &columns_before_image[0], n_bits_len);
7909
1/2
✓ Branch 0 taken 23116717 times.
✗ Branch 1 not taken.
46233434 create_last_word_mask(&m_cols);
7910
1/2
✓ Branch 0 taken 23116717 times.
✗ Branch 1 not taken.
46233434 DBUG_DUMP("m_cols", (uchar *)m_cols.bitmap, no_bytes_in_map(&m_cols));
7911 } // end if columns_before_image.empty()
7912 else {
7913 if (m_cols.bitmap != m_bitbuf) bitmap_free(&m_cols);
7914 m_cols.bitmap = nullptr;
7915 }
7916 } else {
7917 // Needed because bitmap_init() does not set it to null on failure
7918 m_cols.bitmap = nullptr;
7919 common_header->set_is_valid(false);
7920 return;
7921 }
7922 46233434 m_cols_ai.bitmap =
7923 46233434 m_cols.bitmap; // See explanation below while setting is_valid.
7924
7925
2/2
✓ Branch 0 taken 22904200 times.
✓ Branch 1 taken 212517 times.
46233434 if (m_type == binary_log::UPDATE_ROWS_EVENT ||
7926
2/2
✓ Branch 0 taken 22904194 times.
✓ Branch 1 taken 6 times.
45808400 m_type == binary_log::UPDATE_ROWS_EVENT_V1 ||
7927
2/2
✓ Branch 0 taken 6935 times.
✓ Branch 1 taken 22897259 times.
45808388 m_type == binary_log::PARTIAL_UPDATE_ROWS_EVENT) {
7928 /* if bitmap_init fails, is_valid will be set to false*/
7929
2/4
✓ Branch 0 taken 219458 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219458 times.
✗ Branch 3 not taken.
438916 if (likely(!bitmap_init(
7930 &m_cols_ai,
7931 438916 m_width <= sizeof(m_bitbuf_ai) * 8 ? m_bitbuf_ai : nullptr,
7932
2/2
✓ Branch 0 taken 219451 times.
✓ Branch 1 taken 7 times.
438916 m_width))) {
7933
1/2
✓ Branch 0 taken 219458 times.
✗ Branch 1 not taken.
438916 if (!columns_after_image.empty()) {
7934 438916 memcpy(m_cols_ai.bitmap, &columns_after_image[0], n_bits_len);
7935
1/2
✓ Branch 0 taken 219458 times.
✗ Branch 1 not taken.
438916 create_last_word_mask(&m_cols_ai);
7936
1/2
✓ Branch 0 taken 219458 times.
✗ Branch 1 not taken.
438916 DBUG_DUMP("m_cols_ai", (uchar *)m_cols_ai.bitmap,
7937 no_bytes_in_map(&m_cols_ai));
7938 } else {
7939 if (m_cols_ai.bitmap != m_bitbuf_ai) bitmap_free(&m_cols_ai);
7940 m_cols_ai.bitmap = nullptr;
7941 }
7942 } else {
7943 // Needed because bitmap_init() does not set it to null on failure
7944 m_cols_ai.bitmap = nullptr;
7945 common_header->set_is_valid(false);
7946 return;
7947 }
7948 }
7949
7950 /*
7951 m_rows_buf, m_curr_row and m_rows_end are pointers to the vector rows.
7952 m_rows_buf is the pointer to the first byte of first row in the event.
7953 m_curr_row points to current row being applied on the slave. Initially,
7954 this points to the same element as m_rows_buf in the vector.
7955 m_rows_end points to the last byte in the last row in the event.
7956
7957 These pointers are used while applying the events on to the slave, and
7958 are not required for decoding.
7959 */
7960
1/2
✓ Branch 0 taken 23116717 times.
✗ Branch 1 not taken.
46233434 if (likely(!row.empty())) {
7961 46233434 m_rows_buf = &row[0];
7962 #if defined(MYSQL_SERVER)
7963 46164318 m_curr_row = m_rows_buf;
7964 #endif
7965 46233434 m_rows_end = m_rows_buf + row.size() - 1;
7966 46233434 m_rows_cur = m_rows_end;
7967 }
7968
7969
2/4
✓ Branch 0 taken 23116717 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23116717 times.
46233434 if (bitmap_init(&write_set_backup, nullptr, m_cols.n_bits)) {
7970 write_set_backup.bitmap = nullptr; /* purecov: deadcode */
7971 }
7972
7973 /*
7974 -Check that malloc() succeeded in allocating memory for the row
7975 buffer and the COLS vector.
7976 */
7977
2/4
✓ Branch 0 taken 23116717 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23116717 times.
✗ Branch 3 not taken.
92466868 common_header->set_is_valid(m_rows_buf && m_cols.bitmap &&
7978
1/2
✓ Branch 0 taken 23116717 times.
✗ Branch 1 not taken.
46233434 write_set_backup.bitmap);
7979 }
7980
7981 98340352 Rows_log_event::~Rows_log_event() {
7982
1/2
✓ Branch 0 taken 49170387 times.
✗ Branch 1 not taken.
98340352 if (m_cols.bitmap) {
7983
2/2
✓ Branch 0 taken 49168299 times.
✓ Branch 1 taken 2088 times.
98340774 if (m_cols.bitmap == m_bitbuf) // no my_malloc happened
7984 98336598 m_cols.bitmap = nullptr; // so no my_free in bitmap_free
7985 98340774 bitmap_free(&m_cols); // To pair with bitmap_init().
7986 }
7987
2/2
✓ Branch 0 taken 296496 times.
✓ Branch 1 taken 48873893 times.
98340778 if (this->m_local_cols_ai.bitmap != nullptr &&
7988
2/2
✓ Branch 0 taken 31722 times.
✓ Branch 1 taken 264774 times.
592992 this->m_local_cols_ai.bitmap != this->m_local_cols.bitmap) {
7989 63444 bitmap_free(&this->m_local_cols_ai);
7990 }
7991
2/2
✓ Branch 0 taken 296498 times.
✓ Branch 1 taken 48873891 times.
98340778 if (this->m_local_cols.bitmap != nullptr) {
7992 592996 bitmap_free(&this->m_local_cols);
7993 }
7994
7995
1/2
✓ Branch 0 taken 49170622 times.
✗ Branch 1 not taken.
98340776 if (write_set_backup.bitmap) {
7996 98341244 bitmap_free(&write_set_backup);
7997 }
7998 }
7999
8000 #ifdef MYSQL_SERVER
8001 1034190 int Rows_log_event::unpack_current_row(const Relay_log_info *const rli,
8002 MY_BITMAP const *cols,
8003 bool is_after_image, bool only_seek) {
8004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1034190 times.
1034190 assert(m_table);
8005
8006 enum_row_image_type row_image_type;
8007
2/2
✓ Branch 0 taken 738008 times.
✓ Branch 1 taken 296182 times.
1034190 if (is_after_image) {
8008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 738074 times.
738008 assert(get_general_type_code() != binary_log::DELETE_ROWS_EVENT);
8009 1476152 row_image_type = (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT)
8010
2/2
✓ Branch 0 taken 235141 times.
✓ Branch 1 taken 502937 times.
738078 ? enum_row_image_type::UPDATE_AI
8011 : enum_row_image_type::WRITE_AI;
8012 } else {
8013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 296198 times.
296182 assert(get_general_type_code() != binary_log::WRITE_ROWS_EVENT);
8014 592396 row_image_type = (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT)
8015
2/2
✓ Branch 0 taken 235149 times.
✓ Branch 1 taken 61049 times.
296198 ? enum_row_image_type::UPDATE_BI
8016 : enum_row_image_type::DELETE_BI;
8017 }
8018 bool has_value_options =
8019 1034276 (get_type_code() == binary_log::PARTIAL_UPDATE_ROWS_EVENT);
8020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1034240 times.
1034240 ASSERT_OR_RETURN_ERROR(m_curr_row <= m_rows_end, HA_ERR_CORRUPT_EVENT);
8021
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 1034120 times.
1034246 if (::unpack_row(rli, m_table, m_width, m_curr_row, cols, &m_curr_row_end,
8022 1034240 m_rows_end, row_image_type, has_value_options, only_seek)) {
8023 126 int error = thd->get_stmt_da()->mysql_errno();
8024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 assert(error);
8025 126 return error;
8026 }
8027
8028 // After the row is unpacked, we need to update all generated columns
8029 // that aren't included in the row image provided by the source, that is,
8030 // hidden generated columns for functional indexes, generated columns
8031 // that have associated indexes, stored generated columns for which base
8032 // columns have changed and stored generated columns that only exist on
8033 // the replica. We do it in two steps, first all the generated columns
8034 // that aren't functional indexes and then the columns for functional
8035 // indexes, since functional indexes may use generated columns as the
8036 // base column for the index.
8037
2/2
✓ Branch 0 taken 25361 times.
✓ Branch 1 taken 1008718 times.
1034120 if (m_table->has_gcol()) {
8038
2/2
✓ Branch 0 taken 25333 times.
✓ Branch 1 taken 28 times.
25361 if (!only_seek) {
8039 Table_columns_view<> updatable_columns_view{
8040 // A table view for generated columns that need to be updated on the
8041 // replica, excluding columns for functional indexes
8042 25333 this->m_table,
8043 50596 [=](TABLE const *table, size_t column_index) -> bool {
8044 50596 auto field = table->field[column_index];
8045
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 50287 times.
50596 if (field->is_field_for_functional_index()) // Always exclude
8046 // functional indexes
8047 309 return true;
8048
6/6
✓ Branch 0 taken 16894 times.
✓ Branch 1 taken 33393 times.
✓ Branch 2 taken 8495 times.
✓ Branch 3 taken 8399 times.
✓ Branch 4 taken 8495 times.
✓ Branch 5 taken 41792 times.
67181 if (!is_after_image && // Always exclude virtual generated columns
8049 16894 field->is_virtual_gcol()) // if not processing after-image
8050 8495 return true;
8051
2/2
✓ Branch 0 taken 434 times.
✓ Branch 1 taken 41358 times.
41792 if (field->m_indexed) // Never exclude generated columns that
8052 // have indexes
8053 434 return false;
8054
2/2
✓ Branch 0 taken 41329 times.
✓ Branch 1 taken 29 times.
41358 if (bitmap_is_overlapping( // Never exclude generated columns for
8055 // which the base column value changed.
8056 41358 table->write_set, &field->gcol_info->base_columns_map))
8057 41329 return false;
8058
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!is_after_image) // Else, exclude if not in after-image
8059 return true;
8060 return column_index <
8061 29 this->m_cols // Else, exclude generated columns that
8062
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
29 .n_bits || // also exists on the source
8063 29 field->is_virtual_gcol(); // or that are virtual
8064 },
8065
1/2
✓ Branch 0 taken 25333 times.
✗ Branch 1 not taken.
25333 Table_columns_view<>::VFIELDS_ONLY};
8066
8067
3/4
✓ Branch 0 taken 24986 times.
✓ Branch 1 taken 347 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25333 times.
50319 if (updatable_columns_view.filtered_size() != 0 &&
8068
2/4
✓ Branch 0 taken 24986 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24986 times.
24986 this->update_generated_columns(
8069 24986 updatable_columns_view.get_included_fields_bitmap())) {
8070 return thd->get_stmt_da()->mysql_errno(); /* purecov: deadcode */
8071 }
8072
1/2
✓ Branch 0 taken 25333 times.
✗ Branch 1 not taken.
25333 }
8073
4/4
✓ Branch 0 taken 16863 times.
✓ Branch 1 taken 8498 times.
✓ Branch 2 taken 154 times.
✓ Branch 3 taken 25207 times.
42224 if (is_after_image &&
8074
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 16709 times.
16863 !bitmap_is_clear_all(&this->m_table->fields_for_functional_indexes)) {
8075
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 136 times.
154 if (this->update_generated_columns(
8076 154 this->m_table->fields_for_functional_indexes))
8077 18 return thd->get_stmt_da()->mysql_errno(); /* purecov: deadcode */
8078 }
8079 }
8080
8081 1034061 return 0;
8082 }
8083
8084 25140 int Rows_log_event::update_generated_columns(
8085 MY_BITMAP const &fields_to_update) {
8086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25140 times.
25140 assert(!bitmap_is_clear_all(&fields_to_update)); // Do not call this function
8087 // if there is nothing to do
8088 // Readjust the size of the backup bitmap, if needed
8089
2/2
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 25027 times.
25140 if (this->write_set_backup.n_bits != this->m_table->s->fields) {
8090 113 bitmap_free(&this->write_set_backup);
8091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 113 times.
113 if (bitmap_init(&this->write_set_backup, nullptr,
8092 113 this->m_table->s->fields)) {
8093 return HA_ERR_OUT_OF_MEM; /* purecov: deadcode */
8094 }
8095 }
8096 // Make a copy of the write set, and mark all hidden generated columns.
8097 25140 bitmap_copy(&this->write_set_backup, this->m_table->write_set);
8098 25140 bitmap_union(this->m_table->write_set, &fields_to_update);
8099 // Calculate the values for all columns set in param `fields_to_update.
8100 25140 auto res = update_generated_write_fields(&fields_to_update, this->m_table);
8101 // Restore the write set before return
8102 25140 bitmap_copy(this->m_table->write_set, &this->write_set_backup);
8103 25140 return res;
8104 }
8105 #endif // ifdef MYSQL_SERVER
8106
8107 110985431 size_t Rows_log_event::get_data_size() {
8108
1/2
✓ Branch 0 taken 111024911 times.
✗ Branch 1 not taken.
110985431 int const general_type_code = get_general_type_code();
8109
8110 uchar buf[sizeof(m_width) + 1];
8111
1/2
✓ Branch 0 taken 110988347 times.
✗ Branch 1 not taken.
111024911 uchar *end = net_store_length(buf, m_width);
8112
8113
2/6
✓ Branch 0 taken 111000819 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 111000819 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
110988347 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_source",
8114 return 6 + no_bytes_in_map(&m_cols) + (end - buf) +
8115 (general_type_code == binary_log::UPDATE_ROWS_EVENT
8116 ? no_bytes_in_map(&m_cols_ai)
8117 : 0) +
8118 (m_rows_cur - m_rows_buf););
8119
8120 111000819 int data_size = 0;
8121 111000819 bool is_v2_event =
8122 111000819 common_header->type_code > binary_log::DELETE_ROWS_EVENT_V1;
8123
1/2
✓ Branch 0 taken 111008357 times.
✗ Branch 1 not taken.
111000819 if (is_v2_event) {
8124 111008357 data_size = Binary_log_event::ROWS_HEADER_LEN_V2;
8125
2/2
✓ Branch 0 taken 1235 times.
✓ Branch 1 taken 111004898 times.
111008357 if (m_extra_row_info.have_ndb_info())
8126 1235 data_size +=
8127
1/2
✓ Branch 0 taken 1235 times.
✗ Branch 1 not taken.
1235 EXTRA_ROW_INFO_TYPECODE_LENGTH + m_extra_row_info.get_ndb_length();
8128
8129
2/2
✓ Branch 0 taken 33669095 times.
✓ Branch 1 taken 77341028 times.
111006133 if (m_extra_row_info.have_part())
8130 33694866 data_size +=
8131
1/2
✓ Branch 0 taken 33694866 times.
✗ Branch 1 not taken.
33669095 EXTRA_ROW_INFO_TYPECODE_LENGTH + m_extra_row_info.get_part_length();
8132 } else {
8133 data_size = Binary_log_event::ROWS_HEADER_LEN_V1;
8134 }
8135 111028356 data_size += no_bytes_in_map(&m_cols);
8136 111028356 data_size += (uint)(end - buf);
8137
8138
2/2
✓ Branch 0 taken 3051348 times.
✓ Branch 1 taken 107977008 times.
111028356 if (general_type_code == binary_log::UPDATE_ROWS_EVENT)
8139 3051348 data_size += no_bytes_in_map(&m_cols_ai);
8140
8141 111028356 data_size += (uint)(m_rows_cur - m_rows_buf);
8142 111028356 return data_size;
8143 }
8144
8145 #ifdef MYSQL_SERVER
8146 98411911 int Rows_log_event::do_add_row_data(uchar *row_data, size_t length) {
8147 /*
8148 When the table has a primary key, we would probably want, by default, to
8149 log only the primary key value instead of the entire "before image". This
8150 would save binlog space. TODO
8151 */
8152
1/2
✓ Branch 0 taken 98456301 times.
✗ Branch 1 not taken.
98411911 DBUG_TRACE;
8153
4/8
✓ Branch 0 taken 98448695 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 98461814 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
✓ Branch 5 taken 98461788 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
98456301 DBUG_PRINT("enter", ("row_data: %p length: %lu", row_data, (ulong)length));
8154
8155 /*
8156 If length is zero, there is nothing to write, so we just
8157 return. Note that this is not an optimization, since calling
8158 realloc() with size 0 means free().
8159 */
8160
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 98452778 times.
98452788 if (length == 0) {
8161 10 m_row_count++;
8162 10 return 0;
8163 }
8164
8165
1/2
✓ Branch 0 taken 98459278 times.
✗ Branch 1 not taken.
98452778 DBUG_DUMP("row_data", row_data, min<size_t>(length, 32));
8166
8167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98459278 times.
98459278 assert(m_rows_buf <= m_rows_cur);
8168
5/6
✓ Branch 0 taken 72408704 times.
✓ Branch 1 taken 26050574 times.
✓ Branch 2 taken 72411093 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 72394162 times.
✓ Branch 5 taken 16931 times.
98459278 assert(!m_rows_buf || (m_rows_end && m_rows_buf < m_rows_end));
8169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98444736 times.
98444736 assert(m_rows_cur <= m_rows_end);
8170
8171 /* The cast will always work since m_rows_cur <= m_rows_end */
8172
2/2
✓ Branch 0 taken 28601143 times.
✓ Branch 1 taken 69843593 times.
98444736 if (static_cast<size_t>(m_rows_end - m_rows_cur) <= length) {
8173 28601143 size_t const block_size = 1024;
8174 28601143 ulong cur_size = m_rows_cur - m_rows_buf;
8175
2/4
✓ Branch 0 taken 28601211 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28601211 times.
28601143 DBUG_EXECUTE_IF("simulate_too_big_row_case1",
8176 cur_size = UINT_MAX32 - (block_size * 10);
8177 length = UINT_MAX32 - (block_size * 10););
8178
2/4
✓ Branch 0 taken 28601282 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28601282 times.
28601211 DBUG_EXECUTE_IF("simulate_too_big_row_case2",
8179 cur_size = UINT_MAX32 - (block_size * 10);
8180 length = block_size * 10;);
8181
2/4
✓ Branch 0 taken 28601265 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28601265 times.
28601282 DBUG_EXECUTE_IF("simulate_too_big_row_case3", cur_size = block_size * 10;
8182 length = UINT_MAX32 - (block_size * 10););
8183
2/4
✓ Branch 0 taken 28601320 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28601320 times.
28601265 DBUG_EXECUTE_IF("simulate_too_big_row_case4",
8184 cur_size = UINT_MAX32 - (block_size * 10);
8185 length = (block_size * 10) - block_size + 1;);
8186 28601320 ulong remaining_space = UINT_MAX32 - cur_size;
8187 /* Check that the new data fits within remaining space and we can add
8188 block_size without wrapping.
8189 */
8190
3/4
✓ Branch 0 taken 28601326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 309 times.
✓ Branch 3 taken 28601017 times.
28601320 if (length > remaining_space || ((length + block_size) > remaining_space)) {
8191
0/16
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
303 LogErr(ERROR_LEVEL, ER_ROW_DATA_TOO_BIG_TO_WRITE_IN_BINLOG);
8192 return ER_BINLOG_ROW_LOGGING_FAILED;
8193 }
8194 28601017 const size_t new_alloc =
8195 28601017 block_size * ((cur_size + length + block_size - 1) / block_size);
8196
2/4
✓ Branch 0 taken 28601032 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28601096 times.
✗ Branch 3 not taken.
28601017 if (new_alloc) row.resize(new_alloc);
8197
8198 /* If the memory moved, we need to move the pointers */
8199
6/6
✓ Branch 0 taken 28600965 times.
✓ Branch 1 taken 116 times.
✓ Branch 2 taken 27222233 times.
✓ Branch 3 taken 1378746 times.
✓ Branch 4 taken 27222240 times.
✓ Branch 5 taken 1378855 times.
28601081 if (new_alloc && &row[0] != m_rows_buf) {
8200 27222240 m_rows_buf = &row[0];
8201
2/4
✓ Branch 0 taken 27222340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27222365 times.
✗ Branch 3 not taken.
27222284 common_header->set_is_valid(m_rows_buf && m_cols.bitmap);
8202 27222280 m_rows_cur = m_rows_buf + cur_size;
8203 }
8204
8205 /*
8206 The end pointer should always be changed to point to the end of
8207 the allocated memory.
8208 */
8209 28601135 m_rows_end = m_rows_buf + new_alloc;
8210 }
8211
8212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98444728 times.
98444728 assert(m_rows_cur + length <= m_rows_end);
8213 98444728 memcpy(m_rows_cur, row_data, length);
8214 98444728 m_rows_cur += length;
8215 98444728 m_row_count++;
8216 98444728 return 0;
8217 98444738 }
8218
8219 /**
8220 Checks if any of the columns in the given table is
8221 signaled in the bitmap.
8222
8223 For each column in the given table checks if it is
8224 signaled in the bitmap. This is most useful when deciding
8225 whether a before image (BI) can be used or not for
8226 searching a row. If no column is signaled, then the
8227 image cannot be used for searching a record (regardless
8228 of using position(), index scan or table scan). Here is
8229 an example:
8230
8231 MASTER> SET @@binlog_row_image='MINIMAL';
8232 MASTER> CREATE TABLE t1 (a int, b int, c int, primary key(c));
8233 SLAVE> CREATE TABLE t1 (a int, b int);
8234 MASTER> INSERT INTO t1 VALUES (1,2,3);
8235 MASTER> UPDATE t1 SET a=2 WHERE b=2;
8236
8237 For the update statement only the PK (column c) is
8238 logged in the before image (BI). As such, given that
8239 the slave has no column c, it will not be able to
8240 find the row, because BI has no values for the columns
8241 the slave knows about (column a and b).
8242
8243 @param table the table reference on the slave.
8244 @param cols the bitmap signaling columns available in
8245 the BI.
8246
8247 @return true if BI contains usable columns for searching,
8248 false otherwise.
8249 */
8250 85995 static bool is_any_column_signaled_for_table(TABLE *table, MY_BITMAP *cols) {
8251
1/2
✓ Branch 0 taken 85996 times.
✗ Branch 1 not taken.
85995 DBUG_TRACE;
8252
8253 94914 for (Field **ptr = table->field;
8254
5/6
✓ Branch 0 taken 94810 times.
✓ Branch 1 taken 104 times.
✓ Branch 2 taken 94811 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 94810 times.
✓ Branch 5 taken 104 times.
94914 *ptr && ((*ptr)->field_index() < cols->n_bits); ptr++) {
8255
2/2
✓ Branch 0 taken 85893 times.
✓ Branch 1 taken 8918 times.
94810 if (bitmap_is_set(cols, (*ptr)->field_index())) return true;
8256 }
8257
8258 104 return false;
8259 85997 }
8260
8261 /**
8262 Checks if the fields in the given key are signaled in
8263 the bitmap.
8264
8265 Validates whether the before image is usable for the
8266 given key. It can be the case that the before image
8267 does not contain values for the key (eg, master was
8268 using 'minimal' option for image logging and slave has
8269 different index structure on the table). Here is an
8270 example:
8271
8272 MASTER> SET @@binlog_row_image='MINIMAL';
8273 MASTER> CREATE TABLE t1 (a int, b int, c int, primary key(c));
8274 SLAVE> CREATE TABLE t1 (a int, b int, c int, key(a,c));
8275 MASTER> INSERT INTO t1 VALUES (1,2,3);
8276 MASTER> UPDATE t1 SET a=2 WHERE b=2;
8277
8278 When finding the row on the slave, one cannot use the
8279 index (a,c) to search for the row, because there is only
8280 data in the before image for column c. This function
8281 checks the fields needed for a given key and searches
8282 the bitmap to see if all the fields required are
8283 signaled.
8284
8285 @param keyinfo reference to key.
8286 @param cols the bitmap signaling which columns
8287 have available data.
8288
8289 @return true if all fields are signaled in the bitmap
8290 for the given key, false otherwise.
8291 */
8292 47181 static bool are_all_columns_signaled_for_key(KEY *keyinfo, MY_BITMAP *cols) {
8293
1/2
✓ Branch 0 taken 47182 times.
✗ Branch 1 not taken.
47181 DBUG_TRACE;
8294
8295
2/2
✓ Branch 0 taken 51388 times.
✓ Branch 1 taken 42203 times.
93591 for (uint i = 0; i < keyinfo->actual_key_parts; i++) {
8296 51388 uint fieldnr = keyinfo->key_part[i].fieldnr - 1;
8297
6/6
✓ Branch 0 taken 51120 times.
✓ Branch 1 taken 268 times.
✓ Branch 2 taken 4711 times.
✓ Branch 3 taken 46409 times.
✓ Branch 4 taken 4979 times.
✓ Branch 5 taken 46409 times.
51388 if (fieldnr >= cols->n_bits || !bitmap_is_set(cols, fieldnr)) return false;
8298 }
8299
8300 42203 return true;
8301 47182 }
8302
8303 /**
8304 Searches the table for a given key that can be used
8305 according to the existing values, ie, columns set
8306 in the bitmap.
8307
8308 The caller can specify which type of key to find by
8309 setting the following flags in the key_type parameter:
8310
8311 - PRI_KEY_FLAG
8312 Returns the primary key.
8313
8314 - UNIQUE_KEY_FLAG
8315 Returns a unique key (flagged with HA_NOSAME)
8316
8317 - MULTIPLE_KEY_FLAG
8318 Returns a key that is not unique (flagged with HA_NOSAME
8319 and without HA_NULL_PART_KEY) nor PK.
8320
8321 The above flags can be used together, in which case, the
8322 search is conducted in the above listed order. Eg, the
8323 following flag:
8324
8325 (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG)
8326
8327 means that a primary key is returned if it is suitable. If
8328 not then the unique keys are searched. If no unique key is
8329 suitable, then the keys are searched. Finally, if no key
8330 is suitable, MAX_KEY is returned.
8331
8332 @param table reference to the table.
8333 @param bi_cols a bitmap that filters out columns that should
8334 not be considered while searching the key.
8335 Columns that should be considered are set.
8336 @param key_type the type of key to search for.
8337
8338 @return MAX_KEY if no key, according to the key_type specified
8339 is suitable. Returns the key otherwise.
8340
8341 */
8342 76137 static uint search_key_in_table(TABLE *table, MY_BITMAP *bi_cols,
8343 uint key_type) {
8344
1/2
✓ Branch 0 taken 76138 times.
✗ Branch 1 not taken.
76137 DBUG_TRACE;
8345
8346 KEY *keyinfo;
8347 76138 uint res = MAX_KEY;
8348 uint key;
8349
8350
3/4
✓ Branch 0 taken 76138 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31302 times.
✓ Branch 3 taken 44836 times.
76138 if (key_type & PRI_KEY_FLAG && (table->s->primary_key < MAX_KEY)) {
8351
3/8
✓ Branch 0 taken 31302 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31302 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 31302 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
31302 DBUG_PRINT("debug", ("Searching for PK"));
8352 31302 keyinfo = table->s->key_info + table->s->primary_key;
8353
3/4
✓ Branch 0 taken 31302 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27516 times.
✓ Branch 3 taken 3786 times.
31302 if (are_all_columns_signaled_for_key(keyinfo, bi_cols))
8354 27516 return table->s->primary_key;
8355 }
8356
8357
2/2
✓ Branch 0 taken 48621 times.
✓ Branch 1 taken 1 times.
48622 if (key_type & UNIQUE_KEY_FLAG) {
8358
3/8
✓ Branch 0 taken 48621 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48621 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 48621 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
48621 DBUG_PRINT("debug", ("Searching for UK"));
8359 48621 for (key = 0, keyinfo = table->key_info;
8360
3/4
✓ Branch 0 taken 31127 times.
✓ Branch 1 taken 45032 times.
✓ Branch 2 taken 31127 times.
✗ Branch 3 not taken.
76159 (key < table->s->keys) && (res == MAX_KEY); key++, keyinfo++) {
8361 /*
8362 - Unique keys cannot be disabled, thence we skip the check.
8363 - Skip unique keys with nullable parts
8364 - Skip primary keys
8365 - Skip functional indexes if the slave_rows_search_algorithms=INDEX_SCAN
8366 - Skip multi-valued keys as they have only part of value and can't
8367 fully identify a record
8368 */
8369 97168 if (!((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) ||
8370
2/2
✓ Branch 0 taken 4487 times.
✓ Branch 1 taken 3785 times.
8272 (key == table->s->primary_key) ||
8371
1/2
✓ Branch 0 taken 4487 times.
✗ Branch 1 not taken.
4487 ((slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN) &&
8372
2/4
✓ Branch 0 taken 4487 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4487 times.
✗ Branch 3 not taken.
4487 keyinfo->is_functional_index()) ||
8373
7/8
✓ Branch 0 taken 8272 times.
✓ Branch 1 taken 22855 times.
✓ Branch 2 taken 4487 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 4485 times.
✓ Branch 6 taken 26642 times.
✓ Branch 7 taken 4485 times.
39399 keyinfo->flags & HA_MULTI_VALUED_KEY || !keyinfo->is_visible) {
8374 26642 continue;
8375 }
8376
3/4
✓ Branch 0 taken 4485 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3589 times.
✓ Branch 3 taken 896 times.
4485 res = are_all_columns_signaled_for_key(keyinfo, bi_cols) ? key : MAX_KEY;
8377
8378
2/2
✓ Branch 0 taken 3589 times.
✓ Branch 1 taken 896 times.
4485 if (res < MAX_KEY) return res;
8379 }
8380
3/8
✓ Branch 0 taken 45032 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45032 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 45032 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
45032 DBUG_PRINT("debug", ("UK has NULLABLE parts or not all columns signaled."));
8381 }
8382
8383
4/4
✓ Branch 0 taken 22678 times.
✓ Branch 1 taken 22355 times.
✓ Branch 2 taken 13702 times.
✓ Branch 3 taken 8976 times.
45033 if (key_type & MULTIPLE_KEY_FLAG && table->s->keys) {
8384
3/8
✓ Branch 0 taken 13702 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13702 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 13702 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
13702 DBUG_PRINT("debug", ("Searching for K."));
8385 13702 for (key = 0, keyinfo = table->key_info;
8386
3/4
✓ Branch 0 taken 13795 times.
✓ Branch 1 taken 2605 times.
✓ Branch 2 taken 13795 times.
✗ Branch 3 not taken.
16400 (key < table->s->keys) && (res == MAX_KEY); key++, keyinfo++) {
8387 /*
8388 The following indexes are skipped:
8389 - Inactive/invisible indexes.
8390 - UNIQUE NOT NULL indexes.
8391 - Indexes that do not support ha_index_next() e.g. full-text.
8392 - Primary key indexes.
8393 - Functional indexes if the slave_rows_search_algorithms=INDEX_SCAN
8394 - Skip multi-valued keys as they have only part of value and can't
8395 fully identify a record
8396 */
8397
2/4
✓ Branch 0 taken 13795 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13795 times.
✗ Branch 3 not taken.
13795 if (!(table->s->usable_indexes(current_thd).is_set(key)) ||
8398
2/2
✓ Branch 0 taken 11436 times.
✓ Branch 1 taken 2356 times.
13792 ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) ||
8399
2/4
✓ Branch 0 taken 11436 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11436 times.
✗ Branch 3 not taken.
11436 !(table->file->index_flags(key, 0, true) & HA_READ_NEXT) ||
8400
1/2
✓ Branch 0 taken 11436 times.
✗ Branch 1 not taken.
11436 (key == table->s->primary_key) ||
8401
2/2
✓ Branch 0 taken 11399 times.
✓ Branch 1 taken 37 times.
11436 ((slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN) &&
8402
7/8
✓ Branch 0 taken 13792 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 11399 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11358 times.
✓ Branch 5 taken 41 times.
✓ Branch 6 taken 2400 times.
✓ Branch 7 taken 11395 times.
38945 keyinfo->is_functional_index()) ||
8403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11395 times.
11395 keyinfo->flags & HA_MULTI_VALUED_KEY) {
8404 2400 continue;
8405 }
8406
8407
3/4
✓ Branch 0 taken 11395 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11097 times.
✓ Branch 3 taken 298 times.
11395 res = are_all_columns_signaled_for_key(keyinfo, bi_cols) ? key : MAX_KEY;
8408
8409
2/2
✓ Branch 0 taken 11097 times.
✓ Branch 1 taken 298 times.
11395 if (res < MAX_KEY) return res;
8410 }
8411
3/8
✓ Branch 0 taken 2605 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2605 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2605 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2605 DBUG_PRINT("debug", ("Not all columns signaled for K."));
8412 }
8413
8414 33935 return res;
8415 76137 }
8416
8417 296343 void Rows_log_event::decide_row_lookup_algorithm_and_key() {
8418
1/2
✓ Branch 0 taken 296445 times.
✗ Branch 1 not taken.
296343 DBUG_TRACE;
8419
8420 /*
8421 Decision table:
8422 - I --> Index scan / search
8423 - T --> Table scan
8424 - Hi --> Hash over index
8425 - Ht --> Hash over the entire table
8426
8427 |--------------+-----------+------+------+------|
8428 | Index\Option | I , T , H | I, T | I, H | T, H |
8429 |--------------+-----------+------+------+------|
8430 | PK / UK | I | I | I | Hi |
8431 | K | Hi | I | Hi | Hi |
8432 | No Index | Ht | T | Ht | Ht |
8433 |--------------+-----------+------+------+------|
8434
8435 */
8436 296445 TABLE *table = this->m_table;
8437
1/2
✓ Branch 0 taken 296444 times.
✗ Branch 1 not taken.
296445 uint event_type = this->get_general_type_code();
8438 296444 MY_BITMAP *cols = &this->m_cols;
8439 296444 bool delete_update_lookup_condition = false;
8440 296444 this->m_rows_lookup_algorithm = ROW_LOOKUP_NOT_NEEDED;
8441 296444 this->m_key_index = MAX_KEY;
8442 296444 this->m_key_info = nullptr;
8443
8444 // row lookup not needed
8445
4/4
✓ Branch 0 taken 54392 times.
✓ Branch 1 taken 242052 times.
✓ Branch 2 taken 241986 times.
✓ Branch 3 taken 54457 times.
350835 if (event_type == binary_log::WRITE_ROWS_EVENT ||
8446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54391 times.
54391 (delete_update_lookup_condition =
8447
1/2
✓ Branch 0 taken 31704 times.
✗ Branch 1 not taken.
31704 ((event_type == binary_log::DELETE_ROWS_EVENT ||
8448
2/2
✓ Branch 0 taken 46859 times.
✓ Branch 1 taken 7533 times.
54392 event_type == binary_log::UPDATE_ROWS_EVENT) &&
8449
4/6
✓ Branch 0 taken 31704 times.
✓ Branch 1 taken 22688 times.
✓ Branch 2 taken 46858 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 46858 times.
140488 get_flags(COMPLETE_ROWS_F) && !m_table->file->rpl_lookup_rows()))) {
8450 /**
8451 Only TokuDB and RocksDB engines can satisfy delete/update row lookup
8452 optimization, so we don't need to check engine type here.
8453 */
8454
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 241986 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
241986 if (delete_update_lookup_condition && table->s->primary_key == MAX_KEY) {
8455 if (!table->s->rfr_lookup_warning) {
8456 sql_print_warning(
8457 "Slave: read free replication is disabled "
8458 "for TokuDB/RocksDB table `%s.%s` "
8459 "as it does not have implicit primary key, "
8460 "continue with rows lookup",
8461 print_slave_db_safe(table->s->db.str), m_table->s->table_name.str);
8462 table->s->rfr_lookup_warning = true;
8463 }
8464 } else
8465 241986 return;
8466 }
8467
8468
2/2
✓ Branch 0 taken 1388 times.
✓ Branch 1 taken 53069 times.
54457 if (!(slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN))
8469 1388 goto TABLE_OR_INDEX_HASH_SCAN;
8470
8471 /* PK or UK => use LOOKUP_INDEX_SCAN */
8472 53003 this->m_key_index =
8473
1/2
✓ Branch 0 taken 53003 times.
✗ Branch 1 not taken.
53069 search_key_in_table(table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG));
8474
2/2
✓ Branch 0 taken 30650 times.
✓ Branch 1 taken 22353 times.
53003 if (this->m_key_index != MAX_KEY) {
8475
3/8
✓ Branch 0 taken 30650 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30649 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 30649 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
30650 DBUG_PRINT("info",
8476 ("decide_row_lookup_algorithm_and_key: decided - INDEX_SCAN"));
8477 30649 this->m_rows_lookup_algorithm = ROW_LOOKUP_INDEX_SCAN;
8478 30649 goto end;
8479 }
8480
8481 22353 TABLE_OR_INDEX_HASH_SCAN:
8482
8483 /*
8484 NOTE: Engines like Blackhole cannot use HASH_SCAN, because
8485 they do not synchronize reads.
8486 */
8487
4/4
✓ Branch 0 taken 23068 times.
✓ Branch 1 taken 673 times.
✓ Branch 2 taken 678 times.
✓ Branch 3 taken 23063 times.
46809 if (!(slave_rows_search_algorithms_options & SLAVE_ROWS_HASH_SCAN) ||
8488
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 23063 times.
23068 (table->file->ha_table_flags() & HA_READ_OUT_OF_SYNC))
8489 678 goto TABLE_OR_INDEX_FULL_SCAN;
8490
8491 /* search for a key to see if we can narrow the lookup domain further. */
8492
1/2
✓ Branch 0 taken 23064 times.
✗ Branch 1 not taken.
23063 this->m_key_index = search_key_in_table(
8493 table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG));
8494 23064 this->m_rows_lookup_algorithm = ROW_LOOKUP_HASH_SCAN;
8495
2/2
✓ Branch 0 taken 11543 times.
✓ Branch 1 taken 11521 times.
23064 if (m_key_index < MAX_KEY)
8496 11543 m_distinct_key_spare_buf =
8497
1/2
✓ Branch 0 taken 11543 times.
✗ Branch 1 not taken.
11543 (uchar *)thd->alloc(table->key_info[m_key_index].key_length);
8498
3/8
✓ Branch 0 taken 23064 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23064 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 23064 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
23064 DBUG_PRINT("info",
8499 ("decide_row_lookup_algorithm_and_key: decided - HASH_SCAN"));
8500 23064 goto end;
8501
8502 678 TABLE_OR_INDEX_FULL_SCAN:
8503
8504 678 this->m_key_index = MAX_KEY;
8505
8506 /* If we can use an index, try to narrow the scan a bit further. */
8507
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 608 times.
678 if (slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN)
8508
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 this->m_key_index = search_key_in_table(
8509 table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG));
8510
8511
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 668 times.
678 if (this->m_key_index != MAX_KEY) {
8512
3/8
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10 DBUG_PRINT("info",
8513 ("decide_row_lookup_algorithm_and_key: decided - INDEX_SCAN"));
8514 10 this->m_rows_lookup_algorithm = ROW_LOOKUP_INDEX_SCAN;
8515 } else {
8516
3/8
✓ Branch 0 taken 668 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 668 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 668 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
668 DBUG_PRINT("info",
8517 ("decide_row_lookup_algorithm_and_key: decided - TABLE_SCAN"));
8518 668 this->m_rows_lookup_algorithm = ROW_LOOKUP_TABLE_SCAN;
8519 }
8520
8521 54391 end:
8522 /* m_key_index is ready, set m_key_info now. */
8523 54391 m_key_info = m_table->key_info + m_key_index;
8524 /*
8525 m_key_info will influence key comparison code in HASH_SCAN mode,
8526 so the m_distinct_keys set should still be empty.
8527 */
8528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54391 times.
54391 assert(m_distinct_keys.empty());
8529
8530 #ifndef NDEBUG
8531 54391 const char *s =
8532 54391 ((m_rows_lookup_algorithm == Rows_log_event::ROW_LOOKUP_TABLE_SCAN)
8533
2/2
✓ Branch 0 taken 53723 times.
✓ Branch 1 taken 668 times.
108114 ? "TABLE_SCAN"
8534 53723 : ((m_rows_lookup_algorithm == Rows_log_event::ROW_LOOKUP_HASH_SCAN)
8535
2/2
✓ Branch 0 taken 23064 times.
✓ Branch 1 taken 30659 times.
53723 ? "HASH_SCAN"
8536 : "INDEX_SCAN"));
8537
8538 // only for testing purposes
8539 54391 replica_rows_last_search_algorithm_used = m_rows_lookup_algorithm;
8540
3/8
✓ Branch 0 taken 54392 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54392 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 54392 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
54391 DBUG_PRINT("debug", ("Row lookup method: %s", s));
8541 #endif
8542
2/2
✓ Branch 0 taken 54392 times.
✓ Branch 1 taken 241984 times.
296378 }
8543
8544 /*
8545 Encapsulates the operations to be done before applying
8546 row events for update and delete.
8547
8548 @ret value error code
8549 0 success
8550 */
8551 54391 int Rows_log_event::row_operations_scan_and_key_setup() {
8552 54391 int error = 0;
8553
1/2
✓ Branch 0 taken 54392 times.
✗ Branch 1 not taken.
54391 DBUG_TRACE;
8554
8555 /*
8556 Prepare memory structures for search operations. If
8557 search is performed:
8558
8559 1. using hash search => initialize the hash
8560 2. using key => decide on key to use and allocate mem structures
8561 3. using table scan => do nothing
8562 */
8563
1/2
✓ Branch 0 taken 54392 times.
✗ Branch 1 not taken.
54392 decide_row_lookup_algorithm_and_key();
8564
8565
3/3
✓ Branch 0 taken 23064 times.
✓ Branch 1 taken 30660 times.
✓ Branch 2 taken 668 times.
54392 switch (m_rows_lookup_algorithm) {
8566 23064 case ROW_LOOKUP_HASH_SCAN: {
8567
2/4
✓ Branch 0 taken 23064 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23064 times.
23064 if (m_hash.init()) error = HA_ERR_OUT_OF_MEM;
8568 23064 goto err;
8569 }
8570 30660 case ROW_LOOKUP_INDEX_SCAN: {
8571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30660 times.
30660 assert(m_key_index < MAX_KEY);
8572 // Allocate buffer for key searches
8573
1/2
✓ Branch 0 taken 30660 times.
✗ Branch 1 not taken.
30660 m_key = (uchar *)my_malloc(key_memory_log_event, m_key_info->key_length,
8574 MYF(MY_WME));
8575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30660 times.
30660 if (!m_key) error = HA_ERR_OUT_OF_MEM;
8576 30660 goto err;
8577 }
8578 668 case ROW_LOOKUP_TABLE_SCAN:
8579 default:
8580 668 break;
8581 }
8582 54392 err:
8583 54392 return error;
8584 54392 }
8585
8586 /*
8587 Encapsulates the operations to be done after applying
8588 row events for update and delete.
8589
8590 @ret value error code
8591 0 success
8592 */
8593
8594 54389 int Rows_log_event::row_operations_scan_and_key_teardown(int error) {
8595
1/2
✓ Branch 0 taken 54389 times.
✗ Branch 1 not taken.
54389 DBUG_TRACE;
8596
8597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54389 times.
54389 assert(!m_table->file->inited);
8598
3/3
✓ Branch 0 taken 23064 times.
✓ Branch 1 taken 30657 times.
✓ Branch 2 taken 668 times.
54389 switch (m_rows_lookup_algorithm) {
8599 23064 case ROW_LOOKUP_HASH_SCAN: {
8600
1/2
✓ Branch 0 taken 23064 times.
✗ Branch 1 not taken.
23064 m_hash.deinit(); // we don't need the hash anymore.
8601 23064 goto err;
8602 }
8603
8604 30657 case ROW_LOOKUP_INDEX_SCAN: {
8605
1/2
✓ Branch 0 taken 30657 times.
✗ Branch 1 not taken.
30657 if (m_table->s->keys > 0) {
8606
1/2
✓ Branch 0 taken 30657 times.
✗ Branch 1 not taken.
30657 my_free(m_key); // Free for multi_malloc
8607 30657 m_key = nullptr;
8608 30657 m_key_index = MAX_KEY;
8609 30657 m_key_info = nullptr;
8610 }
8611 30657 goto err;
8612 }
8613
8614 668 case ROW_LOOKUP_TABLE_SCAN:
8615 default:
8616 668 break;
8617 }
8618
8619 54389 err:
8620 54389 m_rows_lookup_algorithm = ROW_LOOKUP_UNDEFINED;
8621 54389 return error;
8622 54389 }
8623
8624 1283321 bool Rows_log_event::is_auto_inc_in_extra_columns() {
8625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1283321 times.
1283321 assert(m_table);
8626
2/2
✓ Branch 0 taken 420658 times.
✓ Branch 1 taken 862663 times.
1704030 return (m_table->next_number_field &&
8627 420670 this->m_fields.translate_position(
8628
2/2
✓ Branch 0 taken 748 times.
✓ Branch 1 taken 419961 times.
2124739 m_table->next_number_field->field_index()) >= m_width);
8629 }
8630
8631 11 bool Rows_log_event::is_trx_retryable_upon_engine_error(int error) {
8632
3/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9 times.
11 return (error == HA_ERR_LOCK_DEADLOCK || error == HA_ERR_LOCK_WAIT_TIMEOUT);
8633 }
8634
8635 /*
8636 Compares table->record[0] and table->record[1]
8637
8638 Returns true if different.
8639 */
8640 27417 static bool record_compare(TABLE *table, MY_BITMAP *cols) {
8641
1/2
✓ Branch 0 taken 27417 times.
✗ Branch 1 not taken.
27417 DBUG_TRACE;
8642
8643 /*
8644 Need to set the X bit and the filler bits in both records since
8645 there are engines that do not set it correctly.
8646
8647 In addition, since MyISAM checks that one hasn't tampered with the
8648 record, it is necessary to restore the old bytes into the record
8649 after doing the comparison.
8650
8651 TODO[record format ndb]: Remove it once NDB returns correct
8652 records. Check that the other engines also return correct records.
8653 */
8654
8655
1/2
✓ Branch 0 taken 27417 times.
✗ Branch 1 not taken.
27417 DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
8656
1/2
✓ Branch 0 taken 27417 times.
✗ Branch 1 not taken.
27417 DBUG_DUMP("record[1]", table->record[1], table->s->reclength);
8657
8658 27417 bool result = false;
8659 27417 uchar saved_x[2] = {0, 0}, saved_filler[2] = {0, 0};
8660
8661
1/2
✓ Branch 0 taken 27417 times.
✗ Branch 1 not taken.
27417 if (table->s->null_bytes > 0) {
8662
2/2
✓ Branch 0 taken 54834 times.
✓ Branch 1 taken 27417 times.
82251 for (int i = 0; i < 2; ++i) {
8663 /*
8664 If we have an X bit then we need to take care of it.
8665 */
8666
2/2
✓ Branch 0 taken 16070 times.
✓ Branch 1 taken 38764 times.
54834 if (!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD)) {
8667 16070 saved_x[i] = table->record[i][0];
8668 16070 table->record[i][0] |= 1U;
8669 }
8670
8671 /*
8672 If (last_null_bit_pos == 0 && null_bytes > 1), then:
8673
8674 X bit (if any) + N nullable fields + M Field_bit fields = 8 bits
8675
8676 Ie, the entire byte is used.
8677 */
8678
2/2
✓ Branch 0 taken 53710 times.
✓ Branch 1 taken 1124 times.
54834 if (table->s->last_null_bit_pos > 0) {
8679 53710 saved_filler[i] = table->record[i][table->s->null_bytes - 1];
8680 53710 table->record[i][table->s->null_bytes - 1] |=
8681 53710 256U - (1U << table->s->last_null_bit_pos);
8682 }
8683 }
8684 }
8685
8686 /**
8687 Compare full record only if:
8688 - there are no blob fields (otherwise we would also need
8689 to compare blobs contents as well);
8690 - there are no varchar fields (otherwise we would also need
8691 to compare varchar contents as well);
8692 - there are no null fields, otherwise NULLed fields
8693 contents (i.e., the don't care bytes) may show arbitrary
8694 values, depending on how each engine handles internally.
8695 - if all the bitmap is set (both are full rows)
8696 */
8697 54834 if ((table->s->blob_fields + table->s->varchar_fields +
8698
4/4
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 27314 times.
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 27331 times.
27520 table->s->null_fields) == 0 &&
8699
3/4
✓ Branch 0 taken 103 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 17 times.
103 bitmap_is_set_all(cols)) {
8700 86 result = cmp_record(table, record[1]);
8701 }
8702
8703 /*
8704 Fallback to field-by-field comparison:
8705 1. start by checking if the field is signaled:
8706 2. if it is, first compare the null bit if the field is nullable
8707 3. then compare the contents of the field, if it is not
8708 set to null
8709 */
8710 else {
8711 137297 for (Field **ptr = table->field;
8712
7/8
✓ Branch 0 taken 110198 times.
✓ Branch 1 taken 27099 times.
✓ Branch 2 taken 110198 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 109966 times.
✓ Branch 5 taken 232 times.
✓ Branch 6 taken 109966 times.
✓ Branch 7 taken 27331 times.
137297 *ptr && ((*ptr)->field_index() < cols->n_bits) && !result; ptr++) {
8713 109966 Field *field = *ptr;
8714
4/4
✓ Branch 0 taken 101927 times.
✓ Branch 1 taken 8039 times.
✓ Branch 2 taken 101904 times.
✓ Branch 3 taken 8062 times.
211893 if (bitmap_is_set(cols, field->field_index()) &&
8715
2/2
✓ Branch 0 taken 101904 times.
✓ Branch 1 taken 23 times.
101927 !field->is_virtual_gcol()) {
8716 /* compare null bit */
8717
3/6
✓ Branch 0 taken 101904 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 101904 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 101904 times.
101904 if (field->is_null() != field->is_null_in_record(table->record[1]))
8718 result = true;
8719
8720 /* compare content, only if fields are not set to NULL */
8721
3/4
✓ Branch 0 taken 101904 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100905 times.
✓ Branch 3 taken 999 times.
101904 else if (!field->is_null())
8722
1/2
✓ Branch 0 taken 100905 times.
✗ Branch 1 not taken.
100905 result = field->cmp_binary_offset(table->s->rec_buff_length);
8723 }
8724 }
8725 }
8726
8727 /*
8728 Restore the saved bytes.
8729
8730 TODO[record format ndb]: Remove this code once NDB returns the
8731 correct record format.
8732 */
8733
1/2
✓ Branch 0 taken 27417 times.
✗ Branch 1 not taken.
27417 if (table->s->null_bytes > 0) {
8734
2/2
✓ Branch 0 taken 54834 times.
✓ Branch 1 taken 27417 times.
82251 for (int i = 0; i < 2; ++i) {
8735
2/2
✓ Branch 0 taken 16070 times.
✓ Branch 1 taken 38764 times.
54834 if (!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD))
8736 16070 table->record[i][0] = saved_x[i];
8737
8738
2/2
✓ Branch 0 taken 53710 times.
✓ Branch 1 taken 1124 times.
54834 if (table->s->last_null_bit_pos)
8739 53710 table->record[i][table->s->null_bytes - 1] = saved_filler[i];
8740 }
8741 }
8742
8743 27417 return result;
8744 27417 }
8745
8746 772392 void Rows_log_event::do_post_row_operations(Relay_log_info const *rli,
8747 int error) {
8748 /*
8749 If m_curr_row_end was not set during event execution (e.g., because
8750 of errors) we can't proceed to the next row. If the error is transient
8751 (i.e., error==0 at this point) we must call unpack_current_row() to set
8752 m_curr_row_end.
8753 */
8754
8755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 772432 times.
772392 DBUG_PRINT("info", ("curr_row: %p; curr_row_end: %p; rows_end: %p",
8756 m_curr_row, m_curr_row_end, m_rows_end));
8757
8758
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 772413 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
772413 if (!m_curr_row_end && !error) {
8759 /*
8760 This function is always called immediately following a call to
8761 handle_idempotent_and_ignored_errors which returns 0. And
8762 handle_idempotent_and_ignored_errors can only return 0 when
8763 error==0. And when error==0, it means that the previous call to
8764 unpack_currrent_row was successful. And that means
8765 m_curr_row_end has been set to a valid pointer. So it is
8766 impossible that both error==0 and m_curr_row_end==0 under normal
8767 conditions. So this is probably a case of a corrupt event.
8768 */
8769 const uchar *previous_m_curr_row = m_curr_row;
8770 error = unpack_current_row(rli, &m_cols, true /*is AI*/);
8771
8772 if (!error && previous_m_curr_row == m_curr_row) {
8773 error = 1;
8774 }
8775 }
8776
8777 // at this moment m_curr_row_end should be set
8778
2/4
✓ Branch 0 taken 772420 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 772420 times.
772413 assert(error || m_curr_row_end != nullptr);
8779
3/4
✓ Branch 0 taken 772410 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 772410 times.
772413 assert(error || m_curr_row <= m_curr_row_end);
8780
3/4
✓ Branch 0 taken 772409 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 772409 times.
772413 assert(error || m_curr_row_end <= m_rows_end);
8781
8782 772413 m_curr_row = m_curr_row_end;
8783
8784
6/6
✓ Branch 0 taken 772411 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 397911 times.
✓ Branch 3 taken 374511 times.
✓ Branch 4 taken 397914 times.
✓ Branch 5 taken 374510 times.
772413 if (error == 0 && !m_table->file->has_transactions()) {
8785 397914 thd->get_transaction()->set_unsafe_rollback_flags(Transaction_ctx::SESSION,
8786 true);
8787 397912 thd->get_transaction()->set_unsafe_rollback_flags(Transaction_ctx::STMT,
8788 true);
8789 }
8790
8791 #ifdef HAVE_PSI_STAGE_INTERFACE
8792 /*
8793 Count the number of rows processed unconditionally. Needed instrumentation
8794 may be toggled while a rows event is being processed.
8795 */
8796 772431 m_psi_progress.inc_n_rows_applied(1);
8797
8798
2/2
✓ Branch 0 taken 772413 times.
✓ Branch 1 taken 6 times.
772419 if (m_curr_row > m_rows_buf) {
8799 /* Report progress. */
8800 772413 m_psi_progress.update_work_estimated_and_completed(m_curr_row, m_rows_buf,
8801 772413 m_rows_end);
8802
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 } else if (m_curr_row == m_rows_buf) {
8803 /*
8804 Master can generate an empty row, in the following situation:
8805 mysql> SET SESSION binlog_row_image=MINIMAL;
8806 mysql> CREATE TABLE t1 (c1 INT DEFAULT 100);
8807 mysql> INSERT INTO t1 VALUES ();
8808
8809 Otherwise, m_curr_row must be ahead of m_rows_buf, since we
8810 have processed the first row already.
8811
8812 No point in reporting progress, since this would show for a
8813 very small fraction of time - thence no point in speding extra
8814 CPU cycles for this.
8815
8816 Nevertheless assert that the event is a write event, otherwise,
8817 this should not happen.
8818 */
8819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 assert(get_general_type_code() == binary_log::WRITE_ROWS_EVENT);
8820 } else
8821 /* Impossible */
8822 assert(false);
8823
8824
5/8
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 772387 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 36 times.
772432 DBUG_EXECUTE_IF("dbug.rpl_apply_sync_barrier", {
8825 const char act[] =
8826 "now SIGNAL signal.rpl_row_apply_progress_updated "
8827 "WAIT_FOR signal.rpl_row_apply_process_next_row";
8828 assert(opt_debug_sync_timeout > 0);
8829 assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act)));
8830 };);
8831 #endif /* HAVE_PSI_STAGE_INTERFACE */
8832 772423 }
8833
8834 772769 int Rows_log_event::handle_idempotent_and_ignored_errors(
8835 Relay_log_info const *rli, int *err) {
8836 772769 int error = *err;
8837
2/2
✓ Branch 0 taken 395 times.
✓ Branch 1 taken 772374 times.
772769 if (error) {
8838 395 int actual_error = convert_handler_error(error, thd, m_table);
8839
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 270 times.
520 bool idempotent_error = (idempotent_error_code(error) &&
8840
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 93 times.
125 (rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT));
8841 bool ignored_error =
8842
2/2
✓ Branch 0 taken 363 times.
✓ Branch 1 taken 32 times.
395 (idempotent_error == 0 ? ignored_error_code(actual_error) : 0);
8843
8844
4/4
✓ Branch 0 taken 363 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 309 times.
395 if (idempotent_error || ignored_error) {
8845 loglevel ll;
8846
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 54 times.
86 if (idempotent_error)
8847 32 ll = WARNING_LEVEL;
8848 else
8849 54 ll = INFORMATION_LEVEL;
8850 86 slave_rows_error_report(
8851 ll, error, rli, thd, m_table, get_type_str(),
8852 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
8853 86 (ulong)common_header->log_pos);
8854 86 thd->get_stmt_da()->reset_condition_info(thd);
8855 86 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
8856 79 *err = 0;
8857
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 25 times.
79 if (idempotent_error == 0) return ignored_error;
8858 }
8859 }
8860
8861 772708 return *err;
8862 }
8863
8864 772591 int Rows_log_event::do_apply_row(Relay_log_info const *rli) {
8865
1/2
✓ Branch 0 taken 772675 times.
✗ Branch 1 not taken.
772591 DBUG_TRACE;
8866
8867 772675 int error = 0;
8868
8869 /* in_use can have been set to NULL in close_tables_for_reopen */
8870 772675 THD *old_thd = m_table->in_use;
8871
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 772675 times.
772675 if (!m_table->in_use) m_table->in_use = thd;
8872
8873
1/2
✓ Branch 0 taken 772677 times.
✗ Branch 1 not taken.
772675 error = do_exec_row(rli);
8874
8875
2/2
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 772371 times.
772677 if (error) {
8876
3/8
✓ Branch 0 taken 306 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 306 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 306 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
306 DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
8877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 306 times.
306 assert(error != HA_ERR_RECORD_DELETED);
8878 }
8879 772677 m_table->in_use = old_thd;
8880
8881 772665 return error;
8882 772677 }
8883
8884 /**
8885 Does the cleanup
8886 - closes the index if opened by open_record_scan
8887 - closes the table if opened for scanning.
8888 */
8889 266423 int Rows_log_event::close_record_scan() {
8890
1/2
✓ Branch 0 taken 266423 times.
✗ Branch 1 not taken.
266423 DBUG_TRACE;
8891 266423 int error = 0;
8892
8893 // if there is something to actually close
8894
2/2
✓ Branch 0 taken 254138 times.
✓ Branch 1 taken 12285 times.
266423 if (m_key_index < MAX_KEY) {
8895
3/4
✓ Branch 0 taken 202451 times.
✓ Branch 1 taken 51687 times.
✓ Branch 2 taken 202451 times.
✗ Branch 3 not taken.
254138 if (m_table->file->inited) error = m_table->file->ha_index_end();
8896
2/2
✓ Branch 0 taken 12282 times.
✓ Branch 1 taken 3 times.
12285 } else if (m_table->file->inited)
8897
1/2
✓ Branch 0 taken 12282 times.
✗ Branch 1 not taken.
12282 error = m_table->file->ha_rnd_end();
8898
8899 266423 return error;
8900 266423 }
8901
8902 225997 int Rows_log_event::next_record_scan(bool first_read) {
8903
1/2
✓ Branch 0 taken 225997 times.
✗ Branch 1 not taken.
225997 DBUG_TRACE;
8904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 225997 times.
225997 assert(m_table->file->inited);
8905 225997 TABLE *table = m_table;
8906 225997 int error = 0;
8907
8908
2/2
✓ Branch 0 taken 21174 times.
✓ Branch 1 taken 204823 times.
225997 if (m_key_index >= MAX_KEY)
8909
1/2
✓ Branch 0 taken 21174 times.
✗ Branch 1 not taken.
21174 error = table->file->ha_rnd_next(table->record[0]);
8910 else {
8911 /*
8912 We need to set the null bytes to ensure that the filler bit are
8913 all set when returning. There are storage engines that just set
8914 the necessary bits on the bytes and don't set the filler bits
8915 correctly.
8916 */
8917
1/2
✓ Branch 0 taken 204823 times.
✗ Branch 1 not taken.
204823 if (table->s->null_bytes > 0)
8918 204823 table->record[0][table->s->null_bytes - 1] |=
8919 204823 256U - (1U << table->s->last_null_bit_pos);
8920
8921
2/2
✓ Branch 0 taken 2372 times.
✓ Branch 1 taken 202451 times.
204823 if (!first_read) {
8922 /*
8923 if we fail to fetch next record corresponding to a key value, we
8924 move to the next key value. If we are out of key values as well an error
8925 will be returned.
8926 */
8927 4744 error = table->file->ha_index_next_same(table->record[0], m_key,
8928
1/2
✓ Branch 0 taken 2372 times.
✗ Branch 1 not taken.
2372 m_key_info->key_length);
8929
1/2
✓ Branch 0 taken 2372 times.
✗ Branch 1 not taken.
2372 if (m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN) {
8930 /*
8931 if we are out of rows for this particular key value, we reposition the
8932 marker according to the next key value that we have in the list.
8933 */
8934
2/2
✓ Branch 0 taken 2312 times.
✓ Branch 1 taken 60 times.
2372 if (error) {
8935
2/2
✓ Branch 0 taken 2309 times.
✓ Branch 1 taken 3 times.
2312 if (m_itr != m_distinct_keys.end()) {
8936 2309 m_key = *m_itr;
8937 2309 m_itr++;
8938 2309 first_read = true;
8939 } else {
8940
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
3 if (!is_trx_retryable_upon_engine_error(error))
8941 2 error = HA_ERR_KEY_NOT_FOUND;
8942 }
8943 }
8944 }
8945 }
8946
8947
2/2
✓ Branch 0 taken 204760 times.
✓ Branch 1 taken 63 times.
204823 if (first_read)
8948
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 204752 times.
204760 if ((error = table->file->ha_index_read_map(
8949
1/2
✓ Branch 0 taken 204760 times.
✗ Branch 1 not taken.
204760 table->record[0], m_key, HA_WHOLE_KEY, HA_READ_KEY_EXACT))) {
8950
3/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8 DBUG_PRINT("info", ("no record matching the key found in the table"));
8951
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1 times.
8 if (!is_trx_retryable_upon_engine_error(error))
8952 7 error = HA_ERR_KEY_NOT_FOUND;
8953 }
8954 }
8955
8956 225997 return error;
8957 225997 }
8958
8959 /**
8960 Initializes scanning of rows. Opens an index and initializes an iterator
8961 over a list of distinct keys (m_distinct_keys) if it is a HASH_SCAN
8962 over an index or the table if its a HASH_SCAN over the table.
8963 */
8964 213965 int Rows_log_event::open_record_scan() {
8965 213965 int error = 0;
8966 213965 TABLE *table = m_table;
8967
1/2
✓ Branch 0 taken 213965 times.
✗ Branch 1 not taken.
213965 DBUG_TRACE;
8968
8969
2/2
✓ Branch 0 taken 202451 times.
✓ Branch 1 taken 11514 times.
213965 if (m_key_index < MAX_KEY) {
8970
2/2
✓ Branch 0 taken 11528 times.
✓ Branch 1 taken 190923 times.
202451 if (m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN) {
8971 /* initialize the iterator over the list of distinct keys that we have */
8972 11528 m_itr = m_distinct_keys.begin();
8973
8974 /* get the first element from the list of keys and increment the
8975 iterator
8976 */
8977 11528 m_key = *m_itr;
8978 11528 m_itr++;
8979 } else {
8980 /* this is an INDEX_SCAN we need to store the key in m_key */
8981
2/4
✓ Branch 0 taken 190923 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 190923 times.
✗ Branch 3 not taken.
190923 assert((m_rows_lookup_algorithm == ROW_LOOKUP_INDEX_SCAN) && m_key);
8982
1/2
✓ Branch 0 taken 190923 times.
✗ Branch 1 not taken.
190923 key_copy(m_key, m_table->record[0], m_key_info, 0);
8983 }
8984
8985 /*
8986 Save copy of the record in table->record[1]. It might be needed
8987 later if linear search is used to find exact match.
8988 */
8989 202451 store_record(table, record[1]);
8990
8991
3/8
✓ Branch 0 taken 202451 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 202451 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 202451 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
202451 DBUG_PRINT("info", ("locating record using a key (index_read)"));
8992
8993 /* The m_key_index'th key is active and usable: search the table using the
8994 * index */
8995
2/4
✓ Branch 0 taken 202451 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 202451 times.
404902 if (!table->file->inited &&
8996
2/4
✓ Branch 0 taken 202451 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 202451 times.
202451 (error = table->file->ha_index_init(m_key_index, false))) {
8997 DBUG_PRINT("info", ("ha_index_init returns error %d", error));
8998 goto end;
8999 }
9000
9001
1/2
✓ Branch 0 taken 202451 times.
✗ Branch 1 not taken.
202451 DBUG_DUMP("key data", m_key, m_key_info->key_length);
9002 } else {
9003
2/4
✓ Branch 0 taken 11514 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11514 times.
✗ Branch 3 not taken.
11514 if ((error = table->file->ha_rnd_init(true))) {
9004 DBUG_PRINT("info", ("error initializing table scan"
9005 " (ha_rnd_init returns %d)",
9006 error));
9007 table->file->print_error(error, MYF(0));
9008 }
9009 }
9010
9011 11514 end:
9012 213965 return error;
9013 213965 }
9014
9015 /**
9016 Populates the m_distinct_keys with unique keys to be modified
9017 during HASH_SCAN over keys.
9018 @retval 0 success
9019 */
9020 13866 int Rows_log_event::add_key_to_distinct_keyset() {
9021 13866 int error = 0;
9022
1/2
✓ Branch 0 taken 13866 times.
✗ Branch 1 not taken.
13866 DBUG_TRACE;
9023
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13866 times.
13866 assert(m_key_index < MAX_KEY);
9024
1/2
✓ Branch 0 taken 13866 times.
✗ Branch 1 not taken.
13866 key_copy(m_distinct_key_spare_buf, m_table->record[0], m_key_info, 0);
9025 std::pair<std::set<uchar *, Key_compare>::iterator, bool> ret =
9026
1/2
✓ Branch 0 taken 13866 times.
✗ Branch 1 not taken.
13866 m_distinct_keys.insert(m_distinct_key_spare_buf);
9027
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 13840 times.
13866 if (ret.second) {
9028 /* Insert is successful, so allocate a new buffer for next key */
9029
1/2
✓ Branch 0 taken 13840 times.
✗ Branch 1 not taken.
13840 m_distinct_key_spare_buf = (uchar *)thd->alloc(m_key_info->key_length);
9030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13840 times.
13840 if (!m_distinct_key_spare_buf) {
9031 error = HA_ERR_OUT_OF_MEM;
9032 goto err;
9033 }
9034 }
9035
9036 26 err:
9037 13866 return error;
9038 13866 }
9039
9040 242612 int Rows_log_event::do_index_scan_and_update(Relay_log_info const *rli) {
9041
1/2
✓ Branch 0 taken 242613 times.
✗ Branch 1 not taken.
242612 DBUG_TRACE;
9042
3/4
✓ Branch 0 taken 242613 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 242612 times.
✓ Branch 3 taken 1 times.
242613 assert(m_table && m_table->in_use != nullptr);
9043
9044 242612 int error = 0;
9045 242612 const uchar *saved_m_curr_row = m_curr_row;
9046
9047 /*
9048 rpl_row_tabledefs.test specifies that
9049 if the extra field on the slave does not have a default value
9050 and this is okay with Delete or Update events.
9051 Todo: fix wl3228 hld that requires defaults for all types of events
9052 */
9053
9054
1/2
✓ Branch 0 taken 242612 times.
✗ Branch 1 not taken.
242612 prepare_record(m_table, &this->m_local_cols, false);
9055
3/4
✓ Branch 0 taken 242612 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 242609 times.
242612 if ((error = unpack_current_row(rli, &m_cols, false /*is not AI*/))) goto end;
9056
9057 /*
9058 Trying to do an index scan without a usable key
9059 This is a valid state because we allow the user
9060 to set Slave_rows_search_algorithm= 'INDEX_SCAN'.
9061
9062 Therefore on tables with no indexes we will end
9063 up here.
9064 */
9065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 242609 times.
242609 if (m_key_index >= MAX_KEY) {
9066 error = HA_ERR_END_OF_FILE;
9067 goto end;
9068 }
9069
9070 #ifndef NDEBUG
9071
3/8
✓ Branch 0 taken 242610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 242610 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 242610 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
242609 DBUG_PRINT("info", ("looking for the following record"));
9072
1/2
✓ Branch 0 taken 242610 times.
✗ Branch 1 not taken.
242610 DBUG_DUMP("record[0]", m_table->record[0], m_table->s->reclength);
9073 #endif
9074
9075
2/2
✓ Branch 0 taken 3699 times.
✓ Branch 1 taken 238911 times.
242610 if (m_key_index != m_table->s->primary_key)
9076 /* we dont have a PK, or PK is not usable */
9077 3699 goto INDEX_SCAN;
9078
9079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238911 times.
238911 if ((m_table->file->ha_table_flags() & HA_READ_BEFORE_WRITE_REMOVAL)) {
9080 /*
9081 Read removal is possible since the engine supports write without
9082 previous read using full primary key
9083 */
9084 DBUG_PRINT("info", ("using read before write removal"));
9085 assert(m_key_index == m_table->s->primary_key);
9086
9087 /*
9088 Tell the handler to ignore if key exists or not, since it's
9089 not yet known if the key does exist(when using rbwr)
9090 */
9091 m_table->file->ha_extra(HA_EXTRA_IGNORE_NO_KEY);
9092
9093 goto end;
9094 }
9095
9096
2/2
✓ Branch 0 taken 51687 times.
✓ Branch 1 taken 187224 times.
238911 if ((m_table->file->ha_table_flags() &
9097 HA_PRIMARY_KEY_REQUIRED_FOR_POSITION)) {
9098 /*
9099 Use a more efficient method to fetch the record given by
9100 table->record[0] if the engine allows it. We first compute a
9101 row reference using the position() member function (it will be
9102 stored in table->file->ref) and then use rnd_pos() to position
9103 the "cursor" (i.e., record[0] in this case) at the correct row.
9104
9105 TODO: Check that the correct record has been fetched by
9106 comparing it with the original record. Take into account that the
9107 record on the master and slave can be of different
9108 length. Something along these lines should work:
9109
9110 ADD>>> store_record(table,record[1]);
9111 int error= table->file->rnd_pos(table->record[0],
9112 table->file->ref); ADD>>> assert(memcmp(table->record[1],
9113 table->record[0], table->s->reclength) == 0);
9114
9115 */
9116
9117
3/8
✓ Branch 0 taken 51687 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 51687 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 51687 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
51687 DBUG_PRINT("info", ("locating record using primary key (position)"));
9118
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 51687 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 51687 times.
51687 if (m_table->file->inited && (error = m_table->file->ha_index_end()))
9119 goto end;
9120
9121
1/2
✓ Branch 0 taken 51687 times.
✗ Branch 1 not taken.
51687 error = m_table->file->rnd_pos_by_record(m_table->record[0]);
9122
9123
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 51661 times.
51687 if (error) {
9124
3/8
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 26 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
26 DBUG_PRINT("info", ("rnd_pos returns error %d", error));
9125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (error == HA_ERR_RECORD_DELETED) error = HA_ERR_KEY_NOT_FOUND;
9126 }
9127
9128 51687 goto end;
9129 }
9130
9131 // We can't use position() - try other methods.
9132
9133 187224 INDEX_SCAN:
9134
9135 /* Use the m_key_index'th key */
9136
9137
2/4
✓ Branch 0 taken 190923 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 190923 times.
190923 if ((error = open_record_scan())) goto end;
9138
9139
1/2
✓ Branch 0 taken 190923 times.
✗ Branch 1 not taken.
190923 error = next_record_scan(true);
9140
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 190922 times.
190923 if (error) {
9141
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1 DBUG_PRINT("info", ("no record matching the key found in the table"));
9142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (error == HA_ERR_RECORD_DELETED) error = HA_ERR_KEY_NOT_FOUND;
9143 1 goto end;
9144 }
9145
9146
3/8
✓ Branch 0 taken 190922 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 190922 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 190922 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
190922 DBUG_PRINT("info", ("found first matching record"));
9147
1/2
✓ Branch 0 taken 190922 times.
✗ Branch 1 not taken.
190922 DBUG_DUMP("record[0]", m_table->record[0], m_table->s->reclength);
9148 /*
9149 Below is a minor "optimization". If the key (i.e., key number
9150 0) has the HA_NOSAME flag set, we know that we have found the
9151 correct record (since there can be no duplicates); otherwise, we
9152 have to compare the record with the one found to see if it is
9153 the correct one.
9154
9155 CAVEAT! This behaviour is essential for the replication of,
9156 e.g., the mysql.proc table since the correct record *shall* be
9157 found using the primary key *only*. There shall be no
9158 comparison of non-PK columns to decide if the correct record is
9159 found. I can see no scenario where it would be incorrect to
9160 chose the row to change only using a PK or an UNNI.
9161 */
9162
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 190910 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
190922 if (m_key_info->flags & HA_NOSAME || m_key_index == m_table->s->primary_key) {
9163 /* Unique does not have non nullable part */
9164
1/2
✓ Branch 0 taken 190910 times.
✗ Branch 1 not taken.
190910 if (!(m_key_info->flags & (HA_NULL_PART_KEY)))
9165 190910 goto end; // record found
9166 else {
9167 /*
9168 Unique has nullable part. We need to check if there is any field in the
9169 BI image that is null and part of UNNI.
9170 */
9171 bool null_found = false;
9172 for (uint i = 0; i < m_key_info->user_defined_key_parts && !null_found;
9173 i++) {
9174 uint fieldnr = m_key_info->key_part[i].fieldnr - 1;
9175 Field **f = m_table->field + fieldnr;
9176 null_found = (*f)->is_null();
9177 }
9178
9179 if (!null_found) goto end; // record found
9180
9181 /* else fall through to index scan */
9182 }
9183 }
9184
9185 /*
9186 In case key is not unique, we still have to iterate over records found
9187 and find the one which is identical to the row given. A copy of the
9188 record we are looking for is stored in record[1].
9189 */
9190
3/8
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
12 DBUG_PRINT("info", ("non-unique index, scanning it to find matching record"));
9191
9192
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 while (record_compare(m_table, &this->m_local_cols)) {
9193 while ((error = next_record_scan(false))) {
9194 /* We just skip records that has already been deleted */
9195 if (error == HA_ERR_RECORD_DELETED) continue;
9196 DBUG_PRINT("info", ("no record matching the given row found"));
9197 goto end;
9198 }
9199 }
9200
9201 12 end:
9202
9203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 242613 times.
242613 assert(error != HA_ERR_RECORD_DELETED);
9204
9205
3/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 242583 times.
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
242613 if (error && error != HA_ERR_RECORD_DELETED)
9206
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 m_table->file->print_error(error, MYF(0));
9207 else
9208
1/2
✓ Branch 0 taken 242580 times.
✗ Branch 1 not taken.
242583 error = do_apply_row(rli);
9209
9210
2/2
✓ Branch 0 taken 242531 times.
✓ Branch 1 taken 79 times.
242610 if (!error)
9211
1/2
✓ Branch 0 taken 242531 times.
✗ Branch 1 not taken.
242531 error = close_record_scan();
9212 else
9213 /*
9214 we are already with errors. Keep the error code and
9215 try to close the scan anyway.
9216 */
9217
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
79 (void)close_record_scan();
9218
9219
1/2
✓ Branch 0 taken 242610 times.
✗ Branch 1 not taken.
242610 int unpack_error = skip_after_image_for_update_event(rli, saved_m_curr_row);
9220
2/2
✓ Branch 0 taken 242531 times.
✓ Branch 1 taken 79 times.
242610 if (!error) error = unpack_error;
9221
9222 242610 m_table->default_column_bitmaps();
9223 242610 return error;
9224 242610 }
9225
9226 203122 int Update_rows_log_event::skip_after_image_for_update_event(
9227 const Relay_log_info *rli, const uchar *curr_bi_start) {
9228
4/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 203100 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 6 times.
203122 if (m_curr_row == curr_bi_start && m_curr_row_end != nullptr) {
9229 /*
9230 This handles the case that the BI was read successfully, but an
9231 error happened while looking up the row. In this case, the AI
9232 has not been read, so the read position is between the two
9233 images. In case the error is idempotent, we need to move the
9234 position to the end of the row, and therefore we skip past the
9235 AI.
9236
9237 The normal behavior is:
9238
9239 When unpack_row reads a row image, and there is no error,
9240 unpack_row sets m_curr_row_end to point to the end of the image,
9241 and leaves m_curr_row to point at the beginning.
9242
9243 The AI is read from Update_rows_log_event::do_exec_row. Before
9244 calling unpack_row, do_exec_row sets m_curr_row=m_curr_row_end,
9245 so that it actually reads the AI. And again, if there is no
9246 error, unpack_row sets m_curr_row_end to point to the end of the
9247 AI.
9248
9249 Thus, the positions are moved as follows:
9250
9251 +--------------+--------------+
9252 | BI | AI | NULL
9253 +--------------+--------------+
9254 0. Initial values ^m_curr_row ^m_curr_row_end
9255 1. Read BI, no error
9256 ^m_curr_row ^m_curr_row_end
9257 2. Lookup BI
9258 3. Set m_curr_row
9259 ^m_curr_row
9260 ^m_curr_row_end
9261 4. Read AI, no error
9262 ^m_curr_row ^m_curr_row_end
9263
9264 If an error happened while reading the BI (e.g. corruption),
9265 then we should not try to read the AI here. Therefore we do not
9266 read the AI if m_curr_row_end==NULL.
9267
9268 If an error happened while looking up BI, then we should try to
9269 read AI here. Then we know m_curr_row_end points to beginning of
9270 AI, so we come here, set m_curr_row=m_curr_row_end, and read the
9271 AI.
9272
9273 If an error happened while reading the AI, then we should not
9274 try to read the AI again. Therefore we do not read the AI if
9275 m_curr_row==curr_bi_start.
9276 */
9277 16 m_curr_row = m_curr_row_end;
9278 16 return unpack_current_row(rli, &m_cols_ai, true /*is AI*/,
9279 16 true /*only_seek*/);
9280 }
9281 203106 return 0;
9282 }
9283
9284 26421 int Rows_log_event::do_hash_row(Relay_log_info const *rli) {
9285
1/2
✓ Branch 0 taken 26421 times.
✗ Branch 1 not taken.
26421 DBUG_TRACE;
9286
2/4
✓ Branch 0 taken 26421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26421 times.
✗ Branch 3 not taken.
26421 assert(m_table && m_table->in_use != nullptr);
9287 26421 int error = 0;
9288
9289 /* create an empty entry to add to the hash table */
9290
1/2
✓ Branch 0 taken 26421 times.
✗ Branch 1 not taken.
26421 HASH_ROW_ENTRY *entry = m_hash.make_entry();
9291
9292 /* Prepare the record, unpack and save positions. */
9293 26421 entry->positions->bi_start = m_curr_row; // save the bi start pos
9294
1/2
✓ Branch 0 taken 26421 times.
✗ Branch 1 not taken.
26421 prepare_record(m_table, &this->m_local_cols, false);
9295
3/4
✓ Branch 0 taken 26421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 26418 times.
26421 if ((error = unpack_current_row(rli, &m_cols, false /*is not AI*/))) {
9296 hash_slave_rows_free_entry freer;
9297
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 freer(entry);
9298 3 goto end;
9299 }
9300 26418 entry->positions->bi_ends = m_curr_row_end; // save the bi end pos
9301
9302 /*
9303 Now that m_table->record[0] is filled in, we can add the entry
9304 to the hash table. Note that the put operation calculates the
9305 key based on record[0] contents (including BLOB fields).
9306 */
9307
1/2
✓ Branch 0 taken 26418 times.
✗ Branch 1 not taken.
26418 m_hash.put(m_table, &this->m_local_cols, entry);
9308
9309
3/4
✓ Branch 0 taken 13866 times.
✓ Branch 1 taken 12552 times.
✓ Branch 2 taken 13866 times.
✗ Branch 3 not taken.
26418 if (m_key_index < MAX_KEY) add_key_to_distinct_keyset();
9310
9311 /*
9312 We need to unpack the AI to advance the positions, so we
9313 know when we have reached m_rows_end and that we do not
9314 unpack the AI in the next iteration as if it was a BI.
9315 */
9316
3/4
✓ Branch 0 taken 26418 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10404 times.
✓ Branch 3 taken 16014 times.
26418 if (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT) {
9317 /* Save a copy of the BI. */
9318 16014 store_record(m_table, record[1]);
9319
9320 /*
9321 This is the situation after hashing the BI:
9322
9323 ===|=== before image ====|=== after image ===|===
9324 ^ ^
9325 m_curr_row m_curr_row_end
9326 */
9327
9328 /* Set the position to the start of the record to be unpacked. */
9329 16014 m_curr_row = m_curr_row_end;
9330
9331 /* We shouldn't need this, but lets not leave loose ends */
9332
1/2
✓ Branch 0 taken 16014 times.
✗ Branch 1 not taken.
16014 prepare_record(m_table, &this->m_local_cols, false);
9333 error =
9334
1/2
✓ Branch 0 taken 16014 times.
✗ Branch 1 not taken.
16014 unpack_current_row(rli, &m_cols_ai, true /*is AI*/, true /*only_seek*/);
9335
9336 /*
9337 This is the situation after unpacking the AI:
9338
9339 ===|=== before image ====|=== after image ===|===
9340 ^ ^
9341 m_curr_row m_curr_row_end
9342 */
9343
9344 /* Restore back the copy of the BI. */
9345 16014 restore_record(m_table, record[1]);
9346 }
9347
9348 10404 end:
9349 26421 return error;
9350 26421 }
9351
9352 23042 int Rows_log_event::do_scan_and_update(Relay_log_info const *rli) {
9353
1/2
✓ Branch 0 taken 23042 times.
✗ Branch 1 not taken.
23042 DBUG_TRACE;
9354
2/4
✓ Branch 0 taken 23042 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23042 times.
✗ Branch 3 not taken.
23042 assert(m_table && m_table->in_use != nullptr);
9355
2/4
✓ Branch 0 taken 23042 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23042 times.
23042 assert(m_hash.is_empty() == false);
9356 23042 TABLE *table = m_table;
9357 23042 int error = 0;
9358 23042 const uchar *saved_last_m_curr_row = nullptr;
9359 23042 const uchar *saved_last_m_curr_row_end = nullptr;
9360 /* create an empty entry to add to the hash table */
9361 23042 HASH_ROW_ENTRY *entry = nullptr;
9362 23042 int idempotent_errors = 0;
9363 23042 int i = 0;
9364
9365 23042 saved_last_m_curr_row = m_curr_row;
9366 23042 saved_last_m_curr_row_end = m_curr_row_end;
9367
9368
3/10
✓ Branch 0 taken 23042 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23042 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 23042 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
23042 DBUG_PRINT("info", ("Hash was populated with %d records!", m_hash.size()));
9369
9370 /* open table or index depending on whether we have set m_key_index or not. */
9371
2/4
✓ Branch 0 taken 23042 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23042 times.
23042 if ((error = open_record_scan())) goto err;
9372
9373 /*
9374 Scan the table only once and compare against entries in hash.
9375 When a match is found, apply the changes.
9376 */
9377 do {
9378 /* get the next record from the table */
9379
1/2
✓ Branch 0 taken 35074 times.
✗ Branch 1 not taken.
35074 error = next_record_scan(i == 0);
9380 35074 i++;
9381
9382
5/10
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 34966 times.
✓ Branch 2 taken 108 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 108 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 108 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
35074 if (error) DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
9383
4/4
✓ Branch 0 taken 34966 times.
✓ Branch 1 taken 89 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 11 times.
35074 switch (error) {
9384 34966 case 0: {
9385
1/2
✓ Branch 0 taken 34966 times.
✗ Branch 1 not taken.
34966 entry = m_hash.get(table, &this->m_local_cols);
9386 /**
9387 The do..while loop takes care of the scenario of same row being
9388 updated more than once within a single Update_rows_log_event by
9389 performing the hash lookup for the updated_row(by taking the AI stored
9390 in table->record[0] after the ha_update_row()) when table has no
9391 primary key.
9392
9393 This can happen when update is called from a stored function.
9394 Ex:
9395 CREATE FUNCTION f1 () RETURNS INT BEGIN
9396 UPDATE t1 SET a = 2 WHERE a = 1;
9397 UPDATE t1 SET a = 3 WHERE a = 2;
9398 RETURN 0;
9399 END
9400 */
9401 do {
9402 34989 store_record(table, record[1]);
9403
9404 /**
9405 If there are collisions we need to be sure that this is
9406 indeed the record we want. Loop through all records for
9407 the given key and explicitly compare them against the
9408 record we got from the storage engine.
9409 */
9410
2/2
✓ Branch 0 taken 26394 times.
✓ Branch 1 taken 8595 times.
34989 while (entry) {
9411 26394 m_curr_row = entry->positions->bi_start;
9412 26394 m_curr_row_end = entry->positions->bi_ends;
9413
9414
1/2
✓ Branch 0 taken 26394 times.
✗ Branch 1 not taken.
26394 prepare_record(table, &this->m_local_cols, false);
9415
2/4
✓ Branch 0 taken 26394 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26394 times.
26394 if ((error = unpack_current_row(rli, &m_cols, false /*is not AI*/)))
9416 goto close_table;
9417
9418
2/4
✓ Branch 0 taken 26394 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26394 times.
26394 if (record_compare(table, &this->m_local_cols))
9419 m_hash.next(&entry);
9420 else
9421 26394 break; // we found a match
9422 }
9423
9424 /**
9425 We found the entry we needed, just apply the changes.
9426 */
9427
2/2
✓ Branch 0 taken 26394 times.
✓ Branch 1 taken 8595 times.
34989 if (entry) {
9428 // just to be safe, copy the record from the SE to table->record[0]
9429 26394 restore_record(table, record[1]);
9430
9431 /**
9432 At this point, both table->record[0] and
9433 table->record[1] have the SE row that matched the one
9434 in the hash table.
9435
9436 Thence if this is a DELETE we wouldn't need to mess
9437 around with positions anymore, but since this can be an
9438 update, we need to provide positions so that AI is
9439 unpacked correctly to table->record[0] in UPDATE
9440 implementation of do_exec_row().
9441 */
9442 26394 m_curr_row = entry->positions->bi_start;
9443 26394 m_curr_row_end = entry->positions->bi_ends;
9444
9445 /* we don't need this entry anymore, just delete it */
9446
2/4
✓ Branch 0 taken 26394 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26394 times.
26394 if ((error = m_hash.del(entry))) goto err;
9447
9448
3/4
✓ Branch 0 taken 26394 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 26352 times.
26394 if ((error = do_apply_row(rli))) {
9449
3/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 1 times.
42 if (handle_idempotent_and_ignored_errors(rli, &error))
9450 41 goto close_table;
9451
9452
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 do_post_row_operations(rli, error);
9453 }
9454 }
9455
1/2
✓ Branch 0 taken 34948 times.
✗ Branch 1 not taken.
34948 } while (this->get_general_type_code() ==
9456 24117 binary_log::UPDATE_ROWS_EVENT &&
9457
6/6
✓ Branch 0 taken 24117 times.
✓ Branch 1 taken 10831 times.
✓ Branch 2 taken 21646 times.
✓ Branch 3 taken 2471 times.
✓ Branch 4 taken 23 times.
✓ Branch 5 taken 34925 times.
56594 table->s->primary_key >= MAX_KEY &&
9458
3/4
✓ Branch 0 taken 21646 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 21623 times.
21646 (entry = m_hash.get(table, &m_cols)));
9459 34925 } break;
9460
9461 89 case HA_ERR_RECORD_DELETED:
9462 // get next
9463 89 continue;
9464
9465 8 case HA_ERR_KEY_NOT_FOUND:
9466 /* If the slave exec mode is idempotent or the error is
9467 skipped error, then don't break */
9468
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
8 if (handle_idempotent_and_ignored_errors(rli, &error)) goto close_table;
9469 6 idempotent_errors++;
9470 6 continue;
9471
9472 11 case HA_ERR_END_OF_FILE:
9473 default:
9474 // exception (hash is not empty and we have reached EOF or
9475 // other error happened)
9476 11 goto close_table;
9477 }
9478 }
9479 /**
9480 if the rbr_exec_mode is set to Idempotent, we cannot expect the hash to
9481 be empty. In such cases we count the number of idempotent errors and check
9482 if it is equal to or greater than the number of rows left in the hash.
9483 */
9484
7/10
✓ Branch 0 taken 35020 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12032 times.
✓ Branch 3 taken 22988 times.
✓ Branch 4 taken 12032 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12032 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12032 times.
✓ Branch 9 taken 22988 times.
47052 while (((idempotent_errors < m_hash.size()) && !m_hash.is_empty()) &&
9485
3/4
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 11943 times.
✓ Branch 2 taken 89 times.
✗ Branch 3 not taken.
12032 (!error || (error == HA_ERR_RECORD_DELETED)));
9486
9487 22988 close_table:
9488
3/10
✓ Branch 0 taken 23042 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23042 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 23042 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
23042 DBUG_PRINT("info", ("m_hash.size()=%d error=%d idempotent_errors=%d",
9489 m_hash.size(), error, idempotent_errors));
9490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23042 times.
23042 if (error == HA_ERR_RECORD_DELETED) error = 0;
9491
9492
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 23002 times.
23042 if (error) {
9493
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 table->file->print_error(error, MYF(0));
9494
3/8
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 40 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
40 DBUG_PRINT("info", ("Failed to get next record"
9495 " (ha_rnd_next returns %d)",
9496 error));
9497 /*
9498 we are already with errors. Keep the error code and
9499 try to close the scan anyway.
9500 */
9501
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 (void)close_record_scan();
9502 } else
9503
1/2
✓ Branch 0 taken 23002 times.
✗ Branch 1 not taken.
23002 error = close_record_scan();
9504
9505 23042 err:
9506
9507
10/12
✓ Branch 0 taken 23042 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23023 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 22996 times.
✓ Branch 6 taken 46 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 33 times.
✓ Branch 9 taken 13 times.
✓ Branch 10 taken 23029 times.
✓ Branch 11 taken 13 times.
23042 if ((m_hash.is_empty() && !error) || (idempotent_errors >= m_hash.size())) {
9508 /**
9509 Reset the last positions, because the positions are lost while
9510 handling entries in the hash.
9511 */
9512 23029 m_curr_row = saved_last_m_curr_row;
9513 23029 m_curr_row_end = saved_last_m_curr_row_end;
9514 }
9515
9516 23042 return error;
9517 23042 }
9518
9519 26421 int Rows_log_event::do_hash_scan_and_update(Relay_log_info const *rli) {
9520
1/2
✓ Branch 0 taken 26421 times.
✗ Branch 1 not taken.
26421 DBUG_TRACE;
9521
2/4
✓ Branch 0 taken 26421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26421 times.
✗ Branch 3 not taken.
26421 assert(m_table && m_table->in_use != nullptr);
9522
9523 // HASHING PART
9524
9525 /* unpack the BI (and AI, if it exists) and add it to the hash map. */
9526
3/4
✓ Branch 0 taken 26421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 26418 times.
26421 if (int error = this->do_hash_row(rli)) return error;
9527
9528 /* We have not yet hashed all rows in the buffer. Do not proceed to the SCAN
9529 * part. */
9530
2/2
✓ Branch 0 taken 3376 times.
✓ Branch 1 taken 23042 times.
26418 if (m_curr_row_end < m_rows_end) return 0;
9531
9532
3/10
✓ Branch 0 taken 23042 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23042 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 23042 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
23042 DBUG_PRINT("info", ("Hash was populated with %d records!", m_hash.size()));
9533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23042 times.
23042 assert(m_curr_row_end == m_rows_end);
9534
9535 // SCANNING & UPDATE PART
9536
9537
1/2
✓ Branch 0 taken 23042 times.
✗ Branch 1 not taken.
23042 return this->do_scan_and_update(rli);
9538 26421 }
9539
9540 771 int Rows_log_event::do_table_scan_and_update(Relay_log_info const *rli) {
9541 771 int error = 0;
9542 771 const uchar *saved_m_curr_row = m_curr_row;
9543 771 TABLE *table = m_table;
9544
9545
1/2
✓ Branch 0 taken 771 times.
✗ Branch 1 not taken.
771 DBUG_TRACE;
9546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 771 times.
771 assert(m_curr_row != m_rows_end);
9547
3/8
✓ Branch 0 taken 771 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 771 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 771 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
771 DBUG_PRINT("info", ("locating record using table scan (ha_rnd_next)"));
9548
9549 771 saved_m_curr_row = m_curr_row;
9550
9551 /** unpack the before image */
9552
1/2
✓ Branch 0 taken 771 times.
✗ Branch 1 not taken.
771 prepare_record(table, &this->m_local_cols, false);
9553
3/4
✓ Branch 0 taken 771 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 768 times.
771 if (!(error = unpack_current_row(rli, &m_cols, false /*is not AI*/))) {
9554 /** save a copy so that we can compare against it later */
9555 768 store_record(m_table, record[1]);
9556
9557 768 int restart_count = 0; // Number of times scanning has restarted from top
9558
9559
2/4
✓ Branch 0 taken 768 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 768 times.
768 if ((error = m_table->file->ha_rnd_init(true))) {
9560 DBUG_PRINT("info", ("error initializing table scan"
9561 " (ha_rnd_init returns %d)",
9562 error));
9563 goto end;
9564 }
9565
9566 /* Continue until we find the right record or have made a full loop */
9567 do {
9568 768 restart_ha_rnd_next:
9569
1/2
✓ Branch 0 taken 1020 times.
✗ Branch 1 not taken.
1020 error = m_table->file->ha_rnd_next(m_table->record[0]);
9570
5/10
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1011 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1020 if (error) DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
9571
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1011 times.
✓ Branch 3 taken 1 times.
1020 switch (error) {
9572 8 case HA_ERR_END_OF_FILE:
9573 // restart scan from top
9574
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (++restart_count < 2) {
9575
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if ((error = m_table->file->ha_rnd_init(true))) goto end;
9576 4 goto restart_ha_rnd_next;
9577 }
9578 4 break;
9579
9580 case HA_ERR_RECORD_DELETED:
9581 // fetch next
9582 goto restart_ha_rnd_next;
9583 1011 case 0:
9584 // we're good, check if record matches
9585 1011 break;
9586
9587 1 default:
9588 // exception
9589 1 goto end;
9590 }
9591
7/8
✓ Branch 0 taken 1011 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1011 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 248 times.
✓ Branch 5 taken 763 times.
✓ Branch 6 taken 248 times.
✓ Branch 7 taken 767 times.
1015 } while (restart_count < 2 && record_compare(m_table, &this->m_local_cols));
9592 }
9593
9594 3 end:
9595
9596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 771 times.
771 assert(error != HA_ERR_RECORD_DELETED);
9597
9598 /* either we report error or apply the changes */
9599
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 763 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
771 if (error && error != HA_ERR_RECORD_DELETED) {
9600
3/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8 DBUG_PRINT("info", ("Failed to get next record"
9601 " (ha_rnd_next returns %d)",
9602 error));
9603
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 m_table->file->print_error(error, MYF(0));
9604 } else
9605
1/2
✓ Branch 0 taken 763 times.
✗ Branch 1 not taken.
763 error = do_apply_row(rli);
9606
9607
2/2
✓ Branch 0 taken 721 times.
✓ Branch 1 taken 50 times.
771 if (!error)
9608
1/2
✓ Branch 0 taken 721 times.
✗ Branch 1 not taken.
721 error = close_record_scan();
9609 else
9610 /*
9611 we are already with errors. Keep the error code and
9612 try to close the scan anyway.
9613 */
9614
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 (void)close_record_scan();
9615
9616
1/2
✓ Branch 0 taken 771 times.
✗ Branch 1 not taken.
771 int unpack_error = skip_after_image_for_update_event(rli, saved_m_curr_row);
9617
2/2
✓ Branch 0 taken 721 times.
✓ Branch 1 taken 50 times.
771 if (!error) error = unpack_error;
9618
9619 771 table->default_column_bitmaps();
9620 771 return error;
9621 771 }
9622
9623 299013 int Rows_log_event::do_apply_event(Relay_log_info const *rli) {
9624
1/2
✓ Branch 0 taken 299035 times.
✗ Branch 1 not taken.
299013 DBUG_TRACE;
9625 299035 TABLE *table = nullptr;
9626 299035 int error = 0;
9627
9628 /*
9629 'thd' has been set by exec_relay_log_event(), just before calling
9630 do_apply_event(). We still check here to prevent future coding
9631 errors.
9632 */
9633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 299035 times.
299035 assert(rli->info_thd == thd);
9634
9635 /*
9636 If there is no locks taken, this is the first binrow event seen
9637 after the table map events. We should then lock all the tables
9638 used in the transaction and proceed with execution of the actual
9639 event.
9640 */
9641
2/2
✓ Branch 0 taken 289420 times.
✓ Branch 1 taken 9615 times.
299035 if (!thd->lock) {
9642 /*
9643 Lock_tables() reads the contents of thd->lex, so they must be
9644 initialized.
9645
9646 We also call the mysql_reset_thd_for_next_command(), since this
9647 is the logical start of the next "statement". Note that this
9648 call might reset the value of current_stmt_binlog_format, so
9649 we need to do any changes to that value after this function.
9650 */
9651
1/2
✓ Branch 0 taken 289422 times.
✗ Branch 1 not taken.
289420 lex_start(thd);
9652
1/2
✓ Branch 0 taken 289389 times.
✗ Branch 1 not taken.
289422 mysql_reset_thd_for_next_command(thd);
9653
9654
1/2
✓ Branch 0 taken 289424 times.
✗ Branch 1 not taken.
289389 enum_gtid_statement_status state = gtid_pre_statement_checks(thd);
9655
2/2
✓ Branch 0 taken 287278 times.
✓ Branch 1 taken 2146 times.
289424 if (state == GTID_STATEMENT_EXECUTE) {
9656
2/4
✓ Branch 0 taken 287280 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 287280 times.
287278 if (gtid_pre_statement_post_implicit_commit_checks(thd))
9657 state = GTID_STATEMENT_CANCEL;
9658 }
9659
9660
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 289424 times.
289426 if (state == GTID_STATEMENT_CANCEL) {
9661 2 uint mysql_error = thd->get_stmt_da()->mysql_errno();
9662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(mysql_error != 0);
9663
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 rli->report(ERROR_LEVEL, mysql_error, "Error executing row event: '%s'",
9664 2 thd->get_stmt_da()->message_text());
9665 2 thd->is_slave_error = true;
9666 315 return -1;
9667
2/2
✓ Branch 0 taken 2142 times.
✓ Branch 1 taken 287282 times.
289424 } else if (state == GTID_STATEMENT_SKIP)
9668 2146 goto end;
9669
9670 /*
9671 The current statement is just about to begin and
9672 has not yet modified anything. Note, all.modified is reset
9673 by mysql_reset_thd_for_next_command.
9674 */
9675
1/2
✓ Branch 0 taken 287278 times.
✗ Branch 1 not taken.
287282 thd->get_transaction()->reset_unsafe_rollback_flags(Transaction_ctx::STMT);
9676 /*
9677 This is a row injection, so we flag the "statement" as
9678 such. Note that this code is called both when the slave does row
9679 injections and when the BINLOG statement is used to do row
9680 injections.
9681 */
9682
1/2
✓ Branch 0 taken 287281 times.
✗ Branch 1 not taken.
287278 thd->lex->set_stmt_row_injection();
9683
9684 /*
9685 There are a few flags that are replicated with each row event.
9686 Make sure to set/clear them before executing the main body of
9687 the event.
9688 */
9689
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 287182 times.
287281 if (get_flags(NO_FOREIGN_KEY_CHECKS_F))
9690 73 thd->variables.option_bits |= OPTION_NO_FOREIGN_KEY_CHECKS;
9691 else
9692 287182 thd->variables.option_bits &= ~OPTION_NO_FOREIGN_KEY_CHECKS;
9693
9694
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 287250 times.
287255 if (get_flags(RELAXED_UNIQUE_CHECKS_F))
9695 16 thd->variables.option_bits |= OPTION_RELAXED_UNIQUE_CHECKS;
9696 else
9697 287250 thd->variables.option_bits &= ~OPTION_RELAXED_UNIQUE_CHECKS;
9698
9699 287266 thd->binlog_row_event_extra_data = m_extra_row_info.get_ndb_info();
9700
9701 /* A small test to verify that objects have consistent types */
9702 assert(sizeof(thd->variables.option_bits) ==
9703 sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
9704
2/8
✓ Branch 0 taken 287274 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 287274 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
287253 DBUG_EXECUTE_IF("rows_log_event_before_open_table", {
9705 const char action[] =
9706 "now SIGNAL before_open_table WAIT_FOR go_ahead_sql";
9707 assert(!debug_sync_set_action(thd, STRING_WITH_LEN(action)));
9708 };);
9709
3/4
✓ Branch 0 taken 287211 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 287202 times.
287274 if (open_and_lock_tables(thd, rli->tables_to_lock, 0)) {
9710
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 if (thd->is_error()) {
9711 9 uint actual_error = thd->get_stmt_da()->mysql_errno();
9712
3/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7 times.
9 if (ignored_error_code(actual_error)) {
9713
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (log_error_verbosity >= 2)
9714
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 rli->report(WARNING_LEVEL, actual_error,
9715 "Error executing row event: '%s'",
9716 2 thd->get_stmt_da()->message_text());
9717
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 thd->get_stmt_da()->reset_condition_info(thd);
9718
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
9719 2 error = 0;
9720 2 goto end;
9721 } else {
9722
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 rli->report(ERROR_LEVEL, actual_error,
9723 "Error executing row event: '%s'",
9724 7 thd->get_stmt_da()->message_text());
9725 7 thd->is_slave_error = true;
9726 }
9727 }
9728 7 return 1;
9729 }
9730
9731 /*
9732 When the open and locking succeeded, we check all tables to
9733 ensure that they still have the correct type.
9734 */
9735
9736 {
9737
3/8
✓ Branch 0 taken 287185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 287247 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 287247 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
287202 DBUG_PRINT("debug",
9738 ("Checking compability of tables to lock - tables_to_lock: %p",
9739 rli->tables_to_lock));
9740
9741 /**
9742 When using RBR and MyISAM MERGE tables the base tables that make
9743 up the MERGE table can be appended to the list of tables to lock.
9744
9745 Thus, we just check compatibility for those that tables that have
9746 a correspondent table map event (ie, those that are actually going
9747 to be accessed while applying the event). That's why the loop stops
9748 at rli->tables_to_lock_count .
9749
9750 NOTE: The base tables are added here are removed when
9751 close_thread_tables is called.
9752 */
9753 287259 TABLE_LIST *table_list_ptr = rli->tables_to_lock;
9754
3/4
✓ Branch 0 taken 288317 times.
✓ Branch 1 taken 287020 times.
✓ Branch 2 taken 288322 times.
✗ Branch 3 not taken.
575337 for (uint i = 0; table_list_ptr && (i < rli->tables_to_lock_count);
9755 288078 table_list_ptr = table_list_ptr->next_global, i++) {
9756 /*
9757 Below if condition takes care of skipping base tables that
9758 make up the MERGE table (which are added by open_tables()
9759 call). They are added next to the merge table in the list.
9760 For eg: If RPL_TABLE_LIST is t3->t1->t2 (where t1 and t2
9761 are base tables for merge table 't3'), open_tables will modify
9762 the list by adding t1 and t2 again immediately after t3 in the
9763 list (*not at the end of the list*). New table_to_lock list will
9764 look like t3->t1'->t2'->t1->t2 (where t1' and t2' are TABLE_LIST
9765 objects added by open_tables() call). There is no flag(or logic) in
9766 open_tables() that can skip adding these base tables to the list.
9767 So the logic here should take care of skipping them.
9768
9769 tables_to_lock_count logic will take care of skipping base tables
9770 that are added at the end of the list.
9771 For eg: If RPL_TABLE_LIST is t1->t2->t3, open_tables will modify
9772 the list into t1->t2->t3->t1'->t2'. t1' and t2' will be skipped
9773 because tables_to_lock_count logic in this for loop.
9774 */
9775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 288322 times.
288322 if (table_list_ptr->parent_l) continue;
9776 /*
9777 We can use a down cast here since we know that every table added
9778 to the tables_to_lock is a RPL_TABLE_LIST (or child table which is
9779 skipped above).
9780 */
9781 288322 RPL_TABLE_LIST *ptr = static_cast<RPL_TABLE_LIST *>(table_list_ptr);
9782
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 288322 times.
288322 assert(ptr->m_tabledef_valid);
9783 TABLE *conv_table;
9784
3/4
✓ Branch 0 taken 288338 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 302 times.
✓ Branch 3 taken 288036 times.
288322 if (!ptr->m_tabledef.compatible_with(thd,
9785 const_cast<Relay_log_info *>(rli),
9786 ptr->table, &conv_table)) {
9787
3/8
✓ Branch 0 taken 302 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 302 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 302 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
302 DBUG_PRINT("debug",
9788 ("Table: %s.%s is not compatible with master",
9789 ptr->table->s->db.str, ptr->table->s->table_name.str));
9790
2/2
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 2 times.
302 if (thd->is_slave_error) {
9791
1/2
✓ Branch 0 taken 300 times.
✗ Branch 1 not taken.
300 const_cast<Relay_log_info *>(rli)->slave_close_thread_tables(thd);
9792 300 return ERR_BAD_TABLE_DEF;
9793 } else {
9794
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 thd->get_stmt_da()->reset_condition_info(thd);
9795
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
9796 2 error = 0;
9797 2 goto end;
9798 }
9799 }
9800
3/8
✓ Branch 0 taken 288024 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 288077 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 288077 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
288036 DBUG_PRINT("debug", ("Table: %s.%s is compatible with master"
9801 " - conv_table: %p",
9802 ptr->table->s->db.str,
9803 ptr->table->s->table_name.str, conv_table));
9804 288078 ptr->m_conv_table = conv_table;
9805 }
9806 }
9807
9808 /*
9809 ... and then we add all the tables to the table map and but keep
9810 them in the tables to lock list.
9811 */
9812 287015 TABLE_LIST *ptr = rli->tables_to_lock;
9813
4/4
✓ Branch 0 taken 288083 times.
✓ Branch 1 taken 287020 times.
✓ Branch 2 taken 288082 times.
✓ Branch 3 taken 1 times.
575103 for (uint i = 0; ptr && (i < rli->tables_to_lock_count);
9814 288088 ptr = ptr->next_global, i++) {
9815 /*
9816 Please see comment in above 'for' loop to know the reason
9817 for this if condition
9818 */
9819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 288082 times.
288082 if (ptr->parent_l) continue;
9820
1/2
✓ Branch 0 taken 288088 times.
✗ Branch 1 not taken.
288082 const_cast<Relay_log_info *>(rli)->m_table_map.set_table(ptr->table_id,
9821 ptr->table);
9822 }
9823
9824 /*
9825 Validate applied binlog events with plugin requirements.
9826 */
9827 287021 int out_value = 0;
9828 int hook_error =
9829
4/6
✓ Branch 0 taken 286888 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 176363 times.
✓ Branch 3 taken 110525 times.
✓ Branch 4 taken 110566 times.
✗ Branch 5 not taken.
287021 RUN_HOOK(binlog_relay_io, applier_log_event, (thd, out_value));
9830
3/4
✓ Branch 0 taken 286945 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 286906 times.
286929 if (hook_error || out_value) {
9831 char buf[256];
9832 23 uint applier_error = ER_APPLIER_LOG_EVENT_VALIDATION_ERROR;
9833
9834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (hook_error) {
9835 applier_error = ER_RUN_HOOK_ERROR;
9836 strcpy(buf, "applier_log_event");
9837 } else {
9838
4/8
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
23 if (!thd->owned_gtid_is_empty() && thd->owned_gtid.sidno > 0) {
9839
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 thd->owned_gtid.to_string(thd->owned_sid, buf);
9840 } else {
9841 strcpy(buf, "ANONYMOUS");
9842 }
9843 }
9844
9845
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (thd->slave_thread) {
9846
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 rli->report(ERROR_LEVEL, applier_error,
9847
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ER_THD_NONCONST(thd, applier_error), buf);
9848 3 thd->is_slave_error = true;
9849
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 const_cast<Relay_log_info *>(rli)->slave_close_thread_tables(thd);
9850 } else {
9851 /*
9852 For the cases in which a 'BINLOG' statement is set to
9853 execute in a user session
9854 */
9855
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 my_printf_error(applier_error, ER_THD_NONCONST(thd, applier_error),
9856 MYF(0), buf);
9857 }
9858 6 return applier_error;
9859 }
9860 }
9861
9862 296573 table = m_table =
9863
1/2
✓ Branch 0 taken 296573 times.
✗ Branch 1 not taken.
296521 const_cast<Relay_log_info *>(rli)->m_table_map.get_table(m_table_id);
9864
9865
3/8
✓ Branch 0 taken 296566 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 296568 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 296568 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
296573 DBUG_PRINT("debug",
9866 ("m_table: %p, m_table_id: %llu", m_table, m_table_id.id()));
9867
9868 /*
9869 A row event comprising of a P_S table
9870 - should not be replicated (i.e executed) by the slave SQL thread.
9871 - should not be executed by the client in the form BINLOG '...' stmts.
9872 */
9873
3/4
✓ Branch 0 taken 296496 times.
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 296496 times.
296562 if (table && table->s->table_category == TABLE_CATEGORY_PERFORMANCE)
9874 table = nullptr;
9875
9876
2/2
✓ Branch 0 taken 296498 times.
✓ Branch 1 taken 64 times.
296562 if (table) {
9877
2/4
✓ Branch 0 taken 296491 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 296503 times.
✗ Branch 3 not taken.
296498 this->m_fields.set_thd(thd).set_table(table);
9878
9879 /*
9880 Translate received replicated column bitmaps into local table column
9881 bitmaps. This is needed when the table has columns that are to be excluded
9882 from replication - hidden generated columns, for instance.
9883 */
9884
1/2
✓ Branch 0 taken 296503 times.
✗ Branch 1 not taken.
296503 this->m_fields.translate_bitmap(this->m_cols, this->m_local_cols);
9885
2/2
✓ Branch 0 taken 31725 times.
✓ Branch 1 taken 264778 times.
296503 if (this->m_cols.bitmap != this->m_cols_ai.bitmap)
9886
1/2
✓ Branch 0 taken 31725 times.
✗ Branch 1 not taken.
31725 this->m_fields.translate_bitmap(this->m_cols_ai, this->m_local_cols_ai);
9887 else
9888 264778 this->m_local_cols_ai.bitmap = this->m_local_cols.bitmap;
9889
9890 /*
9891 table == NULL means that this table should not be replicated
9892 (this was set up by Table_map_log_event::do_apply_event()
9893 which tested replicate-* rules).
9894 */
9895
9896
1/2
✓ Branch 0 taken 296452 times.
✗ Branch 1 not taken.
296503 Applier_security_context_guard security_context{rli, thd};
9897 296452 const char *privilege_missing = nullptr;
9898
3/4
✓ Branch 0 taken 296463 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 129 times.
✓ Branch 3 taken 296334 times.
296452 if (!security_context.skip_priv_checks()) {
9899 129 std::vector<std::tuple<ulong, const TABLE *, Rows_log_event *>> l;
9900
4/6
✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
129 switch (get_general_type_code()) {
9901 69 case binary_log::WRITE_ROWS_EVENT: {
9902
2/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
69 l.push_back(std::make_tuple(INSERT_ACL, this->m_table, this));
9903
3/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 53 times.
69 if (!security_context.has_access(l)) {
9904 16 privilege_missing = "INSERT";
9905 }
9906 69 break;
9907 }
9908 18 case binary_log::DELETE_ROWS_EVENT: {
9909
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 l.push_back(std::make_tuple(DELETE_ACL, this->m_table, this));
9910
3/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
18 if (!security_context.has_access(l)) {
9911 9 privilege_missing = "DELETE";
9912 }
9913 18 break;
9914 }
9915 42 case binary_log::UPDATE_ROWS_EVENT:
9916 case binary_log::PARTIAL_UPDATE_ROWS_EVENT: {
9917
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
42 l.push_back(std::make_tuple(UPDATE_ACL, this->m_table, this));
9918
3/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 21 times.
42 if (!security_context.has_access(l)) {
9919 21 privilege_missing = "UPDATE";
9920 }
9921 42 break;
9922 }
9923 default: {
9924 assert(false);
9925 }
9926 }
9927 129 }
9928
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 296417 times.
296463 if (privilege_missing != nullptr) {
9929
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
138 rli->report(ERROR_LEVEL, ER_TABLEACCESS_DENIED_ERROR,
9930
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 ER_THD(thd, ER_TABLEACCESS_DENIED_ERROR), privilege_missing,
9931
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
92 security_context.get_username().data(),
9932 46 security_context.get_hostname().data(),
9933
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 table->s->table_name.str);
9934 46 return ER_TABLEACCESS_DENIED_ERROR;
9935 }
9936
9937 296417 bool no_columns_to_update = false;
9938 // set the database
9939 LEX_CSTRING thd_db;
9940 296417 LEX_CSTRING current_db_name_saved = thd->db();
9941 296355 thd_db.str = table->s->db.str;
9942 296355 thd_db.length = table->s->db.length;
9943
1/2
✓ Branch 0 taken 296448 times.
✗ Branch 1 not taken.
296355 thd->reset_db(thd_db);
9944
1/2
✓ Branch 0 taken 296424 times.
✗ Branch 1 not taken.
296448 thd->set_command(COM_QUERY);
9945 296424 PSI_stage_info *stage = nullptr;
9946
9947 /*
9948 It's not needed to set_time() but
9949 1) it continues the property that "Time" in SHOW PROCESSLIST shows how
9950 much slave is behind
9951 2) it will be needed when we allow replication from a table with no
9952 TIMESTAMP column to a table with one.
9953 So we call set_time(), like in SBR. Presently it changes nothing.
9954 */
9955
1/2
✓ Branch 0 taken 296434 times.
✗ Branch 1 not taken.
296424 thd->set_time(&(common_header->when));
9956
9957 /*
9958 We don't consider index extensions in RBR, as doing so would cause
9959 replication failure with UPDATE/DELETE when replica server has a PK on
9960 extra columns and source does not.
9961 */
9962 592886 Disable_index_extensions_switch_guard guard(thd);
9963
9964 296411 thd->binlog_row_event_extra_data = m_extra_row_info.get_ndb_info();
9965
9966 /*
9967 Now we are in a statement and will stay in a statement until we
9968 see a STMT_END_F.
9969
9970 We set this flag here, before actually applying any rows, in
9971 case the SQL thread is stopped and we need to detect that we're
9972 inside a statement and halting abruptly might cause problems
9973 when restarting.
9974 */
9975 296421 const_cast<Relay_log_info *>(rli)->set_flag(Relay_log_info::IN_STMT);
9976
9977
7/8
✓ Branch 0 taken 294975 times.
✓ Branch 1 taken 1459 times.
✓ Branch 2 taken 294938 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 287890 times.
✓ Branch 5 taken 7048 times.
✓ Branch 6 taken 287889 times.
✓ Branch 7 taken 8508 times.
296417 if (m_width == this->m_fields.filtered_size() && bitmap_is_set_all(&m_cols))
9978 287889 set_flags(COMPLETE_ROWS_F);
9979
9980 /*
9981 Set tables write and read sets.
9982
9983 Read_set contains all slave columns (in case we are going to fetch
9984 a complete record from slave)
9985
9986 Write_set equals the m_cols bitmap sent from master but it can be
9987 longer if slave has extra columns.
9988 */
9989
9990 296361 bitmap_set_all(table->read_set);
9991 296380 bitmap_set_all(table->write_set);
9992
9993 /*
9994 Call mark_generated_columns() to set read_set/write_set bits of the
9995 virtual generated columns as required in order to get these computed.
9996 This is needed since all columns need to have a value in the before
9997 image for the record when doing the update (some storage engines will
9998 use this for maintaining of secondary indexes). This call is required
9999 even for DELETE events to set write_set bit in order to satisfy
10000 ASSERTs in Field_*::store functions.
10001
10002 binlog_prepare_row_image() function, which will be called from
10003 binlogging functions (binlog_update_row() and binlog_delete_row())
10004 will take care of removing these spurious fields required during
10005 execution but not needed for binlogging. In case of inserts, there
10006 are no spurious fields (all generated columns are required to be written
10007 into the binlog).
10008 */
10009
4/6
✓ Branch 0 taken 296352 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22688 times.
✓ Branch 3 taken 31703 times.
✓ Branch 4 taken 241961 times.
✗ Branch 5 not taken.
296428 switch (get_general_type_code()) {
10010 22688 case binary_log::DELETE_ROWS_EVENT:
10011
1/2
✓ Branch 0 taken 22688 times.
✗ Branch 1 not taken.
22688 bitmap_intersect(table->read_set, &this->m_local_cols);
10012 22688 stage = &stage_rpl_apply_row_evt_delete;
10013
3/4
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 22611 times.
✓ Branch 2 taken 77 times.
✗ Branch 3 not taken.
22688 if (m_table->vfield) m_table->mark_generated_columns(false);
10014 22688 break;
10015 31703 case binary_log::UPDATE_ROWS_EVENT:
10016
1/2
✓ Branch 0 taken 31704 times.
✗ Branch 1 not taken.
31703 bitmap_intersect(table->read_set, &this->m_local_cols);
10017
1/2
✓ Branch 0 taken 31704 times.
✗ Branch 1 not taken.
31704 bitmap_intersect(table->write_set, &this->m_local_cols_ai);
10018
3/4
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 31502 times.
✓ Branch 2 taken 202 times.
✗ Branch 3 not taken.
31704 if (m_table->vfield) m_table->mark_generated_columns(true);
10019 /* Skip update rows events that don't have data for this server's table.
10020 */
10021
3/4
✓ Branch 0 taken 31704 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
✓ Branch 3 taken 31604 times.
31704 if (!is_any_column_signaled_for_table(table, &this->m_local_cols_ai))
10022 100 no_columns_to_update = true;
10023 31704 stage = &stage_rpl_apply_row_evt_update;
10024 31704 break;
10025 241961 case binary_log::WRITE_ROWS_EVENT:
10026 /*
10027 For 'WRITE_ROWS_EVENT, the execution order for 'mark_generated_rows()'
10028 and bitset intersection between 'write_set' and 'm_cols', is inverted.
10029 This behaviour is necessary due to an inconsistency, between storage
10030 engines, regarding the 'm_cols' bitset and generated columns: while
10031 non-NDB engines always include the generated columns for write-rows
10032 events, NDB doesn't if not necessary. The previous execution order
10033 would set all generated columns bits to '1' in 'write_set', since
10034 'mark_generated_columns()' is expecting that every column is present
10035 in the log event. This would break replication of generated columns
10036 for NDB.
10037
10038 For engines that include every column in write-rows events, this order
10039 makes no difference, assuming that the master uses the same engine,
10040 since the master will include all the bits in the image.
10041
10042 For use-cases that use different storage engines, specifically NDB
10043 and some other, this order may break replication due to the
10044 differences in behaviour regarding generated columns bits, in
10045 wrote-rows event bitsets. This issue should be further addressed by
10046 storage engines handlers, by converging behaviour regarding such use
10047 cases.
10048 */
10049 /* WRITE ROWS EVENTS store the bitmap in the m_cols bitmap */
10050
3/4
✓ Branch 0 taken 3586 times.
✓ Branch 1 taken 238375 times.
✓ Branch 2 taken 3586 times.
✗ Branch 3 not taken.
241961 if (m_table->vfield) m_table->mark_generated_columns(false);
10051
1/2
✓ Branch 0 taken 242026 times.
✗ Branch 1 not taken.
241961 bitmap_intersect(table->write_set, &this->m_local_cols);
10052 242026 stage = &stage_rpl_apply_row_evt_write;
10053 242026 break;
10054 default:
10055 assert(false);
10056 }
10057
10058
2/2
✓ Branch 0 taken 293631 times.
✓ Branch 1 taken 2787 times.
296418 if (thd->slave_thread) // set the mode for slave
10059 293631 this->rbr_exec_mode = replica_exec_mode_options;
10060 else // set the mode for user thread
10061 2787 this->rbr_exec_mode = thd->variables.rbr_exec_mode_options;
10062
10063 // Do event specific preparations
10064
1/2
✓ Branch 0 taken 296392 times.
✗ Branch 1 not taken.
296418 error = do_before_row_operations(rli);
10065
10066 /*
10067 Bug#56662 Assertion failed: next_insert_id == 0, file handler.cc
10068 Don't allow generation of auto_increment value when processing
10069 rows event by setting 'MODE_NO_AUTO_VALUE_ON_ZERO'. The exception
10070 to this rule happens when the auto_inc column exists on some
10071 extra columns on the slave. In that case, do not force
10072 MODE_NO_AUTO_VALUE_ON_ZERO.
10073 */
10074 296392 sql_mode_t saved_sql_mode = thd->variables.sql_mode;
10075
3/4
✓ Branch 0 taken 296431 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 296247 times.
✓ Branch 3 taken 184 times.
296392 if (!is_auto_inc_in_extra_columns())
10076 296247 thd->variables.sql_mode |= MODE_NO_AUTO_VALUE_ON_ZERO;
10077
10078 // row processing loop
10079
10080 /*
10081 set the initial time of this ROWS statement if it was not done
10082 before in some other ROWS event.
10083 */
10084 296431 const_cast<Relay_log_info *>(rli)->set_row_stmt_start_timestamp();
10085
10086 296388 const uchar *saved_m_curr_row = m_curr_row;
10087
10088 296388 int (Rows_log_event::*do_apply_row_ptr)(Relay_log_info const *) = nullptr;
10089
10090 /**
10091 Skip update rows events that don't have data for this slave's
10092 table.
10093 */
10094
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 296288 times.
296388 if (no_columns_to_update) goto AFTER_MAIN_EXEC_ROW_LOOP;
10095
10096 /**
10097 If there are no columns marked in the read_set for this table,
10098 that means that we cannot lookup any row using the available BI
10099 in the binary log. Thence, we immediately raise an error:
10100 HA_ERR_END_OF_FILE.
10101 */
10102
10103
4/4
✓ Branch 0 taken 54291 times.
✓ Branch 1 taken 241997 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 296286 times.
350580 if ((m_rows_lookup_algorithm != ROW_LOOKUP_NOT_NEEDED) &&
10104
3/4
✓ Branch 0 taken 54292 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 54289 times.
54291 !is_any_column_signaled_for_table(table, &this->m_local_cols)) {
10105 3 error = HA_ERR_END_OF_FILE;
10106 3 goto AFTER_MAIN_EXEC_ROW_LOOP;
10107 }
10108
5/5
✓ Branch 0 taken 23045 times.
✓ Branch 1 taken 30576 times.
✓ Branch 2 taken 668 times.
✓ Branch 3 taken 241964 times.
✓ Branch 4 taken 33 times.
296286 switch (m_rows_lookup_algorithm) {
10109 23045 case ROW_LOOKUP_HASH_SCAN:
10110 23045 do_apply_row_ptr = &Rows_log_event::do_hash_scan_and_update;
10111 23045 break;
10112
10113 30576 case ROW_LOOKUP_INDEX_SCAN:
10114 30576 do_apply_row_ptr = &Rows_log_event::do_index_scan_and_update;
10115 30576 break;
10116
10117 668 case ROW_LOOKUP_TABLE_SCAN:
10118 668 do_apply_row_ptr = &Rows_log_event::do_table_scan_and_update;
10119 668 break;
10120
10121 241964 case ROW_LOOKUP_NOT_NEEDED:
10122
2/12
✓ Branch 0 taken 241980 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 241980 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
241964 assert(get_general_type_code() == binary_log::WRITE_ROWS_EVENT ||
10123 get_general_type_code() == binary_log::DELETE_ROWS_EVENT ||
10124 get_general_type_code() == binary_log::UPDATE_ROWS_EVENT);
10125
10126 /* No need to scan for rows, just apply it */
10127 241980 do_apply_row_ptr = &Rows_log_event::do_apply_row;
10128 241980 break;
10129
10130 33 default:
10131 33 assert(0);
10132 error = 1;
10133 goto AFTER_MAIN_EXEC_ROW_LOOP;
10134 break;
10135 }
10136
10137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 296269 times.
296269 assert(stage != nullptr);
10138
1/2
✓ Branch 0 taken 296340 times.
✗ Branch 1 not taken.
296269 THD_STAGE_INFO(thd, *stage);
10139
10140 #ifdef HAVE_PSI_STAGE_INTERFACE
10141
1/2
✓ Branch 0 taken 296348 times.
✗ Branch 1 not taken.
296340 m_psi_progress.set_progress(mysql_set_stage(stage->m_key));
10142 #endif
10143
10144 do {
10145
3/8
✓ Branch 0 taken 772741 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 772740 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 772740 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
772732 DBUG_PRINT("info", ("calling do_apply_row_ptr"));
10146
10147
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 772742 times.
✓ Branch 2 taken 772734 times.
✗ Branch 3 not taken.
772742 error = (this->*do_apply_row_ptr)(rli);
10148
10149
2/2
✓ Branch 0 taken 772386 times.
✓ Branch 1 taken 348 times.
772734 if (!error) thd->updated_row_count++;
10150
10151
3/4
✓ Branch 0 taken 772717 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 320 times.
✓ Branch 3 taken 772397 times.
772734 if (handle_idempotent_and_ignored_errors(rli, &error)) break;
10152
10153 /* this advances m_curr_row */
10154
1/2
✓ Branch 0 taken 772407 times.
✗ Branch 1 not taken.
772397 do_post_row_operations(rli, error);
10155
10156
3/4
✓ Branch 0 taken 772408 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 476403 times.
✓ Branch 3 taken 296005 times.
772407 } while (!error && (m_curr_row != m_rows_end));
10157
10158
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 296321 times.
296324 if (unlikely(opt_userstat)) {
10159 7 thd->update_stats(false);
10160
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 update_global_user_stats(thd, true, my_getsystime());
10161 }
10162
10163 #ifdef HAVE_PSI_STAGE_INTERFACE
10164 296328 m_psi_progress.end_work();
10165 #endif
10166
10167 296425 AFTER_MAIN_EXEC_ROW_LOOP:
10168
10169
6/6
✓ Branch 0 taken 296123 times.
✓ Branch 1 taken 302 times.
✓ Branch 2 taken 36343 times.
✓ Branch 3 taken 259795 times.
✓ Branch 4 taken 36345 times.
✓ Branch 5 taken 260095 times.
296425 if (saved_m_curr_row != m_curr_row && !table->file->has_transactions()) {
10170 /*
10171 Usually, the trans_commit_stmt() propagates unsafe_rollback_flags
10172 from statement to transaction level. However, we cannot rely on
10173 this when row format is in use as several events can be processed
10174 before calling this function. This happens because it is called
10175 only when the latest event generated by a statement is processed.
10176
10177 There are however upper level functions that execute per event
10178 and check transaction's status. So if the unsafe_rollback_flags
10179 are not propagated here, this can lead to errors.
10180
10181 For example, a transaction that updates non-transactional tables
10182 may be stopped in the middle thus leading to inconsistencies
10183 after a restart.
10184 */
10185
1/2
✓ Branch 0 taken 36350 times.
✗ Branch 1 not taken.
36345 thd->get_transaction()->mark_modified_non_trans_table(
10186 Transaction_ctx::STMT);
10187
1/2
✓ Branch 0 taken 36348 times.
✗ Branch 1 not taken.
36350 thd->get_transaction()->merge_unsafe_rollback_flags();
10188 }
10189
10190 /*
10191 Restore the sql_mode after the rows event is processed.
10192 */
10193 296443 thd->variables.sql_mode = saved_sql_mode;
10194
10195 {
10196 /*
10197 The following failure injecion works in cooperation with tests
10198 setting @@global.debug= 'd,stop_replica_middle_group'.
10199 The sql thread receives the killed status and will proceed
10200 to shutdown trying to finish incomplete events group.
10201 */
10202
2/8
✓ Branch 0 taken 296445 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 296445 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
296443 DBUG_EXECUTE_IF("stop_replica_middle_group", {
10203 if (thd->get_transaction()->cannot_safely_rollback(
10204 Transaction_ctx::SESSION)) {
10205 auto thd_rli = (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL
10206 ? const_cast<Relay_log_info *>(rli)
10207 : static_cast<Slave_worker *>(
10208 const_cast<Relay_log_info *>(rli))
10209 ->c_rli);
10210 thd_rli->abort_slave = 1;
10211 }
10212 };);
10213 }
10214
10215
4/6
✓ Branch 0 taken 296426 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 283 times.
✓ Branch 3 taken 296143 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 296426 times.
296728 if ((error = do_after_row_operations(rli, error)) &&
10216
3/6
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 283 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 283 times.
283 ignored_error_code(convert_handler_error(error, thd, table))) {
10217 slave_rows_error_report(
10218 INFORMATION_LEVEL, error, rli, thd, table, get_type_str(),
10219 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
10220 (ulong)common_header->log_pos);
10221 thd->get_stmt_da()->reset_condition_info(thd);
10222 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
10223 error = 0;
10224 }
10225
10226 // reset back the db
10227
1/2
✓ Branch 0 taken 296452 times.
✗ Branch 1 not taken.
296426 thd->reset_db(current_db_name_saved);
10228
2/2
✓ Branch 0 taken 296441 times.
✓ Branch 1 taken 48 times.
296486 } // if (table)
10229
10230
2/2
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 296222 times.
296505 if (error) {
10231
2/4
✓ Branch 0 taken 281 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 283 times.
✗ Branch 3 not taken.
283 slave_rows_error_report(
10232 ERROR_LEVEL, error, rli, thd, table, get_type_str(),
10233 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
10234 283 (ulong)common_header->log_pos);
10235 /*
10236 @todo We should probably not call
10237 reset_current_stmt_binlog_format_row() from here.
10238 /Sven
10239 */
10240
1/2
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
283 thd->reset_current_stmt_binlog_format_row();
10241 283 thd->is_slave_error = true;
10242 283 return error;
10243 }
10244
10245 296222 end:
10246
2/2
✓ Branch 0 taken 288755 times.
✓ Branch 1 taken 9624 times.
298368 if (get_flags(STMT_END_F)) {
10247
3/4
✓ Branch 0 taken 288719 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 288714 times.
288755 if ((error = rows_event_stmt_cleanup(rli, thd))) {
10248
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (table)
10249
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 slave_rows_error_report(
10250
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 ERROR_LEVEL, thd->is_error() ? 0 : error, rli, thd, table,
10251 get_type_str(),
10252 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
10253 4 (ulong)common_header->log_pos);
10254 else {
10255
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 rli->report(
10256 ERROR_LEVEL,
10257
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 thd->is_error() ? thd->get_stmt_da()->mysql_errno() : error,
10258 "Error in cleaning up after an event of type:%s; %s; the group"
10259 " log file/position: %s %lu",
10260 get_type_str(),
10261
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 thd->is_error() ? thd->get_stmt_da()->message_text()
10262 : "unexpected error",
10263 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
10264 1 (ulong)common_header->log_pos);
10265 }
10266 }
10267 /* We are at end of the statement (STMT_END_F flag), lets clean
10268 the memory which was used from thd's mem_root now.
10269 This needs to be done only if we are here in SQL thread context.
10270 In other flow ( in case of a regular thread which can happen
10271 when the thread is applying BINLOG'...' row event) we should
10272 *not* try to free the memory here. It will be done latter
10273 in dispatch_command() after command execution is completed.
10274 */
10275
3/4
✓ Branch 0 taken 286012 times.
✓ Branch 1 taken 2707 times.
✓ Branch 2 taken 286052 times.
✗ Branch 3 not taken.
288719 if (thd->slave_thread) thd->mem_root->ClearForReuse();
10276 }
10277 298383 return error;
10278 299029 }
10279
10280 296415 Log_event::enum_skip_reason Rows_log_event::do_shall_skip(Relay_log_info *rli) {
10281 /*
10282 If the slave skip counter is 1 and this event does not end a
10283 statement, then we should not start executing on the next event.
10284 Otherwise, we defer the decision to the normal skipping logic.
10285 */
10286
6/6
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 296132 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 278 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 296410 times.
296415 if (rli->slave_skip_counter == 1 && !get_flags(STMT_END_F))
10287 5 return Log_event::EVENT_SKIP_IGNORE;
10288 else
10289 296410 return Log_event::do_shall_skip(rli);
10290 }
10291
10292 /**
10293 The function is called at Rows_log_event statement commit time,
10294 normally from Rows_log_event::do_update_pos() and possibly from
10295 Query_log_event::do_apply_event() of the COMMIT.
10296 The function commits the last statement for engines, binlog and
10297 releases resources have been allocated for the statement.
10298
10299 @retval 0 Ok.
10300 @retval non-zero Error at the commit.
10301 */
10302
10303 288725 static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD *thd) {
10304
1/2
✓ Branch 0 taken 288771 times.
✗ Branch 1 not taken.
288725 DBUG_TRACE;
10305
5/8
✓ Branch 0 taken 288770 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 288769 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
288771 DBUG_EXECUTE_IF("simulate_rows_event_cleanup_failure", {
10306 char errbuf[MYSQL_ERRMSG_SIZE];
10307 int err = 149;
10308 my_error(ER_ERROR_DURING_COMMIT, MYF(0), err,
10309 my_strerror(errbuf, MYSQL_ERRMSG_SIZE, err));
10310 return 1;
10311 });
10312 int error;
10313 {
10314 /*
10315 This is the end of a statement or transaction, so close (and
10316 unlock) the tables we opened when processing the
10317 Table_map_log_event starting the statement.
10318
10319 OBSERVER. This will clear *all* mappings, not only those that
10320 are open for the table. There is not good handle for on-close
10321 actions for tables.
10322
10323 NOTE. Even if we have no table ('table' == 0) we still need to be
10324 here, so that we increase the group relay log position. If we didn't, we
10325 could have a group relay log position which lags behind "forever"
10326 (assume the last master's transaction is ignored by the slave because of
10327 replicate-ignore rules).
10328 */
10329
1/2
✓ Branch 0 taken 288771 times.
✗ Branch 1 not taken.
288769 error = thd->binlog_flush_pending_rows_event(true);
10330
10331 /*
10332 If this event is not in a transaction, the call below will, if some
10333 transactional storage engines are involved, commit the statement into
10334 them and flush the pending event to binlog.
10335 If this event is in a transaction, the call will do nothing, but a
10336 Xid_log_event will come next which will, if some transactional engines
10337 are involved, commit the transaction and flush the pending event to the
10338 binlog.
10339 If there was a deadlock the transaction should have been rolled back
10340 already. So there should be no need to rollback the transaction.
10341 */
10342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 288771 times.
288771 assert(!thd->transaction_rollback_request);
10343
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 288771 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
288771 error |= ((error != 0) ? static_cast<int>(trans_rollback_stmt(thd))
10344
1/2
✓ Branch 0 taken 288768 times.
✗ Branch 1 not taken.
288771 : static_cast<int>(trans_commit_stmt(thd)));
10345
10346 /*
10347 Now what if this is not a transactional engine? we still need to
10348 flush the pending event to the binlog; we did it with
10349 thd->binlog_flush_pending_rows_event(). Note that we imitate
10350 what is done for real queries: a call to
10351 ha_autocommit_or_rollback() (sometimes only if involves a
10352 transactional engine), and a call to be sure to have the pending
10353 event flushed.
10354 */
10355
10356 /*
10357 @todo We should probably not call
10358 reset_current_stmt_binlog_format_row() from here.
10359
10360 Btw, the previous comment about transactional engines does not
10361 seem related to anything that happens here.
10362 /Sven
10363 */
10364
1/2
✓ Branch 0 taken 288775 times.
✗ Branch 1 not taken.
288768 thd->reset_current_stmt_binlog_format_row();
10365
10366
1/2
✓ Branch 0 taken 288763 times.
✗ Branch 1 not taken.
288775 const_cast<Relay_log_info *>(rli)->cleanup_context(thd, false);
10367
10368 /*
10369 Clean sql_command value
10370 */
10371 288763 thd->lex->sql_command = SQLCOM_END;
10372 }
10373 288763 return error;
10374 288764 }
10375
10376 /**
10377 The method either increments the relay log position or
10378 commits the current statement and increments the master group
10379 position if the event is STMT_END_F flagged and
10380 the statement corresponds to the autocommit query (i.e replicated
10381 without wrapping in BEGIN/COMMIT)
10382
10383 @retval 0 Success
10384 @retval non-zero Error in the statement commit
10385 */
10386 443 int Rows_log_event::do_update_pos(Relay_log_info *rli) {
10387
1/2
✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
443 DBUG_TRACE;
10388 443 int error = 0;
10389
10390
3/10
✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 443 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 443 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
443 DBUG_PRINT("info", ("flags: %s", get_flags(STMT_END_F) ? "STMT_END_F " : ""));
10391
10392 /* Worker does not execute binlog update position logics */
10393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 443 times.
443 assert(!is_mts_worker(rli->info_thd));
10394
10395
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 43 times.
443 if (get_flags(STMT_END_F)) {
10396 /*
10397 Indicate that a statement is finished.
10398 Step the group log position if we are not in a transaction,
10399 otherwise increase the event log position.
10400 */
10401
1/2
✓ Branch 0 taken 400 times.
✗ Branch 1 not taken.
400 error = rli->stmt_done(common_header->log_pos);
10402 } else {
10403 43 rli->inc_event_relay_log_pos();
10404 }
10405
10406 443 return error;
10407 443 }
10408
10409 26052921 bool Rows_log_event::write_data_header(Basic_ostream *ostream) {
10410 uchar
10411 buf[Binary_log_event::ROWS_HEADER_LEN_V2]; // No need to init the buffer
10412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26053173 times.
26052921 assert(m_table_id.is_valid());
10413
2/6
✓ Branch 0 taken 26053165 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26053165 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
26053173 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_source", {
10414 int4store(buf + 0, (ulong)m_table_id.id());
10415 int2store(buf + 4, m_flags);
10416 return (wrapper_my_b_safe_write(ostream, buf, 6));
10417 });
10418 26053165 int6store(buf + ROWS_MAPID_OFFSET, m_table_id.id());
10419 26053055 int2store(buf + ROWS_FLAGS_OFFSET, m_flags);
10420
1/2
✓ Branch 0 taken 26053012 times.
✗ Branch 1 not taken.
26053098 if (likely(!log_bin_use_v1_row_events)) {
10421 /*
10422 v2 event, with variable header portion.
10423 Determine length of variable header payload(extra_row_info part)
10424 */
10425 26053012 uint extra_row_info_payloadlen = EXTRA_ROW_INFO_HEADER_LENGTH;
10426
2/2
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 26052321 times.
26053012 if (m_extra_row_info.have_ndb_info()) {
10427 623 extra_row_info_payloadlen +=
10428
1/2
✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
623 (EXTRA_ROW_INFO_TYPECODE_LENGTH + m_extra_row_info.get_ndb_length());
10429 ;
10430 }
10431
10432
2/2
✓ Branch 0 taken 15391782 times.
✓ Branch 1 taken 10661249 times.
26052944 if (m_extra_row_info.have_part()) {
10433 15391782 extra_row_info_payloadlen +=
10434
1/2
✓ Branch 0 taken 15391782 times.
✗ Branch 1 not taken.
15391782 (EXTRA_ROW_INFO_TYPECODE_LENGTH + m_extra_row_info.get_part_length());
10435 }
10436 /* Var-size header len includes len itself */
10437 26053031 int2store(buf + ROWS_VHLEN_OFFSET, extra_row_info_payloadlen);
10438
2/4
✓ Branch 0 taken 26053302 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26053302 times.
26053015 if (wrapper_my_b_safe_write(ostream, buf,
10439 Binary_log_event::ROWS_HEADER_LEN_V2))
10440 return true;
10441
10442 /* Write var-sized payload, if any */
10443
2/2
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 26052691 times.
26053302 if (m_extra_row_info.have_ndb_info()) {
10444 /* Add tag and extra row info */
10445 623 uint8 type_code = static_cast<uint8>(enum_extra_row_info_typecode::NDB);
10446
2/4
✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 623 times.
623 if (wrapper_my_b_safe_write(ostream, &(type_code),
10447 EXTRA_ROW_INFO_TYPECODE_LENGTH))
10448 return true;
10449
2/4
✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 623 times.
623 if (wrapper_my_b_safe_write(ostream, m_extra_row_info.get_ndb_info(),
10450
1/2
✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
623 m_extra_row_info.get_ndb_length()))
10451 return true;
10452 }
10453
2/2
✓ Branch 0 taken 15391993 times.
✓ Branch 1 taken 10661197 times.
26053314 if (m_extra_row_info.have_part()) {
10454 uint8 type_code;
10455 15391993 type_code = static_cast<uint8>(enum_extra_row_info_typecode::PART);
10456 uchar partition_buf[5];
10457 15391993 uint8 extra_part_info_data_len = 0;
10458 15391993 partition_buf[extra_part_info_data_len++] = type_code;
10459
10460 // partition_id occupies less than 2 bytes
10461 // in all the cases because of the current range of allowed number
10462 // of partitions 8192 for non-ndb and 12288 for ndb.
10463 // So while writing the partition_id it is okay to use 2 bytes for it.
10464
10465 15391993 int write_partition_id = m_extra_row_info.get_partition_id();
10466 15391783 int2store(partition_buf + extra_part_info_data_len,
10467 static_cast<uint16>(write_partition_id));
10468 15391783 extra_part_info_data_len += EXTRA_ROW_PART_INFO_VALUE_LENGTH;
10469
10470
3/4
✓ Branch 0 taken 15391783 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35390 times.
✓ Branch 3 taken 15356393 times.
15391783 if (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT) {
10471 35390 write_partition_id = m_extra_row_info.get_source_partition_id();
10472 35390 int2store(partition_buf + extra_part_info_data_len,
10473 static_cast<uint16>(write_partition_id));
10474 35390 extra_part_info_data_len += EXTRA_ROW_PART_INFO_VALUE_LENGTH;
10475 }
10476
10477
2/4
✓ Branch 0 taken 15391783 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 15391783 times.
15391783 if (wrapper_my_b_safe_write(ostream, partition_buf,
10478 extra_part_info_data_len))
10479 return true;
10480 }
10481 } else {
10482 if (wrapper_my_b_safe_write(ostream, buf,
10483 Binary_log_event::ROWS_HEADER_LEN_V1))
10484 return true;
10485 }
10486
10487 26052980 return false;
10488 }
10489
10490 26052911 bool Rows_log_event::write_data_body(Basic_ostream *ostream) {
10491 /*
10492 Note that this should be the number of *bits*, not the number of
10493 bytes.
10494 */
10495 uchar sbuf[sizeof(m_width) + 1];
10496 26052911 ptrdiff_t const data_size = m_rows_cur - m_rows_buf;
10497 26052911 bool res = false;
10498
1/2
✓ Branch 0 taken 26053086 times.
✗ Branch 1 not taken.
26052911 uchar *const sbuf_end = net_store_length(sbuf, (size_t)m_width);
10499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26053086 times.
26053086 assert(static_cast<size_t>(sbuf_end - sbuf) <= sizeof(sbuf));
10500
10501
1/2
✓ Branch 0 taken 26053084 times.
✗ Branch 1 not taken.
26053086 DBUG_DUMP("m_width", sbuf, (size_t)(sbuf_end - sbuf));
10502 26053272 res =
10503
4/6
✓ Branch 0 taken 26053099 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26053287 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 26053262 times.
26053084 res || wrapper_my_b_safe_write(ostream, sbuf, (size_t)(sbuf_end - sbuf));
10504
10505
1/2
✓ Branch 0 taken 26053208 times.
✗ Branch 1 not taken.
26053272 DBUG_DUMP("m_cols", (uchar *)m_cols.bitmap, no_bytes_in_map(&m_cols));
10506
4/4
✓ Branch 0 taken 26053207 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 26053291 times.
52106521 res = res || wrapper_my_b_safe_write(ostream, (uchar *)m_cols.bitmap,
10507
1/2
✓ Branch 0 taken 26053313 times.
✗ Branch 1 not taken.
26053207 no_bytes_in_map(&m_cols));
10508 /*
10509 TODO[refactor write]: Remove the "down cast" here (and elsewhere).
10510 */
10511
3/4
✓ Branch 0 taken 26053200 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 440011 times.
✓ Branch 3 taken 25613189 times.
26053314 if (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT) {
10512
1/2
✓ Branch 0 taken 440011 times.
✗ Branch 1 not taken.
440011 DBUG_DUMP("m_cols_ai", (uchar *)m_cols_ai.bitmap,
10513 no_bytes_in_map(&m_cols_ai));
10514
2/4
✓ Branch 0 taken 440011 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 440011 times.
880022 res = res || wrapper_my_b_safe_write(ostream, (uchar *)m_cols_ai.bitmap,
10515
1/2
✓ Branch 0 taken 440011 times.
✗ Branch 1 not taken.
440011 no_bytes_in_map(&m_cols_ai));
10516 }
10517
1/2
✓ Branch 0 taken 26053073 times.
✗ Branch 1 not taken.
26053200 DBUG_DUMP("rows", m_rows_buf, data_size);
10518
4/6
✓ Branch 0 taken 26053089 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26053288 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 26053282 times.
26053073 res = res || wrapper_my_b_safe_write(ostream, m_rows_buf, (size_t)data_size);
10519
10520 26053272 return res;
10521 }
10522
10523 35400 int Rows_log_event::pack_info(Protocol *protocol) {
10524 char buf[256];
10525
2/2
✓ Branch 0 taken 32389 times.
✓ Branch 1 taken 3011 times.
35400 char const *const flagstr = get_flags(STMT_END_F) ? " flags: STMT_END_F" : "";
10526 size_t bytes =
10527 35400 snprintf(buf, sizeof(buf), "table_id: %llu%s", m_table_id.id(), flagstr);
10528
1/2
✓ Branch 0 taken 35400 times.
✗ Branch 1 not taken.
35400 protocol->store_string(buf, bytes, &my_charset_bin);
10529 35400 return 0;
10530 }
10531 #endif // MYSQL_SERVER
10532
10533 #ifndef MYSQL_SERVER
10534 30004 void Rows_log_event::print_helper(FILE *,
10535 PRINT_EVENT_INFO *print_event_info) const {
10536 30004 IO_CACHE *const head = &print_event_info->head_cache;
10537 30004 IO_CACHE *const body = &print_event_info->body_cache;
10538
2/2
✓ Branch 0 taken 30002 times.
✓ Branch 1 taken 2 times.
30004 if (!print_event_info->short_form) {
10539 30002 bool const last_stmt_event = get_flags(STMT_END_F);
10540 30002 print_header(head, print_event_info, !last_stmt_event);
10541
2/2
✓ Branch 0 taken 29734 times.
✓ Branch 1 taken 268 times.
60004 my_b_printf(head, "\t%s: table id %llu%s\n", get_type_str(),
10542 30002 m_table_id.id(), last_stmt_event ? " flags: STMT_END_F" : "");
10543 30002 print_base64(body, print_event_info, !last_stmt_event);
10544 }
10545 30004 }
10546 #endif
10547
10548 /**************************************************************************
10549 Table_map_log_event member functions and support functions
10550 **************************************************************************/
10551
10552 /**
10553 @ingroup Replication
10554
10555 @page PAGE_RPL_FIELD_METADATA How replication of field metadata works.
10556
10557 When a table map is created, the master first calls
10558 Table_map_log_event::save_field_metadata() which calculates how many
10559 values will be in the field metadata. Only those fields that require the
10560 extra data are added. The method also loops through all of the fields in
10561 the table calling the method Field::save_field_metadata() which returns the
10562 values for the field that will be saved in the metadata and replicated to
10563 the slave. Once all fields have been processed, the table map is written to
10564 the binlog adding the size of the field metadata and the field metadata to
10565 the end of the body of the table map.
10566
10567 When a table map is read on the slave, the field metadata is read from the
10568 table map and passed to the table_def class constructor which saves the
10569 field metadata from the table map into an array based on the type of the
10570 field. Field metadata values not present (those fields that do not use extra
10571 data) in the table map are initialized as zero (0). The array size is the
10572 same as the columns for the table on the slave.
10573
10574 Additionally, values saved for field metadata on the master are saved as a
10575 string of bytes (uchar) in the binlog. A field may require 1 or more bytes
10576 to store the information. In cases where values require multiple bytes
10577 (e.g. values > 255), the endian-safe methods are used to properly encode
10578 the values on the master and decode them on the slave. When the field
10579 metadata values are captured on the slave, they are stored in an array of
10580 type uint. This allows the least number of casts to prevent casting bugs
10581 when the field metadata is used in comparisons of field attributes. When
10582 the field metadata is used for calculating addresses in pointer math, the
10583 type used is uint32.
10584 */
10585
10586 #if defined(MYSQL_SERVER)
10587 /**
10588 Save the field metadata based on the real_type of the field.
10589 The metadata saved depends on the type of the field. Some fields
10590 store a single byte for pack_length() while others store two bytes
10591 for field_length (max length).
10592
10593 @retval 0 Ok.
10594
10595 @todo
10596 We may want to consider changing the encoding of the information.
10597 Currently, the code attempts to minimize the number of bytes written to
10598 the tablemap. There are at least two other alternatives; 1) using
10599 net_store_length() to store the data allowing it to choose the number of
10600 bytes that are appropriate thereby making the code much easier to
10601 maintain (only 1 place to change the encoding), or 2) use a fixed number
10602 of bytes for each field. The problem with option 1 is that net_store_length()
10603 will use one byte if the value < 251, but 3 bytes if it is > 250. Thus,
10604 for fields like CHAR which can be no larger than 255 characters, the method
10605 will use 3 bytes when the value is > 250. Further, every value that is
10606 encoded using 2 parts (e.g., pack_length, field_length) will be numerically
10607 > 250 therefore will use 3 bytes for eah value. The problem with option 2
10608 is less wasteful for space but does waste 1 byte for every field that does
10609 not encode 2 parts.
10610 */
10611 10438420 int Table_map_log_event::save_field_metadata() {
10612
1/2
✓ Branch 0 taken 10438665 times.
✗ Branch 1 not taken.
10438420 DBUG_TRACE;
10613 10438665 int index = 0;
10614
6/10
✓ Branch 0 taken 10438791 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35267120 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 45705901 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 45706004 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 35267237 times.
✓ Branch 9 taken 10438765 times.
45705559 for (auto it = this->m_fields.begin(); it != this->m_fields.end(); ++it) {
10615
1/2
✓ Branch 0 taken 35267252 times.
✗ Branch 1 not taken.
35267237 Field *field = *it;
10616
5/8
✓ Branch 0 taken 35266730 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35266808 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 260 times.
✓ Branch 5 taken 35266548 times.
✓ Branch 6 taken 260 times.
✗ Branch 7 not taken.
35267252 DBUG_PRINT("debug", ("field_type: %d", m_coltype[it.filtered_pos()]));
10617
1/2
✓ Branch 0 taken 35266783 times.
✗ Branch 1 not taken.
35266808 index += field->save_field_metadata(&m_field_metadata[index]);
10618
10619
5/6
✓ Branch 0 taken 35266894 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 35266892 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
35266783 DBUG_EXECUTE_IF("inject_invalid_blob_size", {
10620 if (m_coltype[it.filtered_pos()] == MYSQL_TYPE_BLOB)
10621 m_field_metadata[index - 1] = 5;
10622 });
10623 10438765 }
10624 10438673 return index;
10625 10438778 }
10626
10627 /*
10628 Constructor used to build an event for writing to the binary log.
10629 Mats says tbl->s lives longer than this event so it's ok to copy pointers
10630 (tbl->s->db etc) and not pointer content.
10631 */
10632
10633 10438023 Table_map_log_event::Table_map_log_event(THD *thd_arg, TABLE *tbl,
10634 10438023 const Table_id &tid, bool using_trans)
10635 : binary_log::Table_map_event(
10636 tid,
10637 20876359 tbl->s->fields +
10638
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10438327 times.
10438336 DBUG_EVALUATE_IF("binlog_omit_last_column_from_table_map_event",
10639 -1, 0),
10640 31314159 (tbl->s->db.str), ((tbl->s->db.str) ? tbl->s->db.length : 0),
10641 10438023 (tbl->s->table_name.str), (tbl->s->table_name.length)),
10642 Log_event(thd_arg, 0,
10643 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
10644 : Log_event::EVENT_STMT_CACHE,
10645 Log_event::EVENT_NORMAL_LOGGING, header(), footer()),
10646
5/8
✓ Branch 0 taken 10438113 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10126928 times.
✓ Branch 3 taken 311409 times.
✓ Branch 4 taken 10438330 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10438770 times.
✗ Branch 7 not taken.
20876359 m_fields{tbl, Replicated_columns_view::OUTBOUND} {
10647 10438770 common_header->type_code = binary_log::TABLE_MAP_EVENT;
10648 10438770 m_table = tbl;
10649 10438770 m_flags = TM_BIT_LEN_EXACT_F;
10650
10651 10438193 this->m_colcnt =
10652 10438770 this->m_fields.filtered_size() +
10653
3/4
✓ Branch 0 taken 10438193 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 10438184 times.
10438004 DBUG_EVALUATE_IF("binlog_omit_last_column_from_table_map_event", -1, 0);
10654
10655 uchar cbuf[sizeof(m_colcnt) + 1];
10656 uchar *cbuf_end;
10657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438267 times.
10438193 assert(m_table_id.is_valid());
10658 /*
10659 In TABLE_SHARE, "db" and "table_name" are 0-terminated (see this comment in
10660 table.cc / alloc_table_share():
10661 Use the fact the key is db/0/table_name/0
10662 As we rely on this let's assert it.
10663 */
10664
3/4
✓ Branch 0 taken 10438261 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10438261 times.
10438267 assert((tbl->s->db.str == nullptr) ||
10665 (tbl->s->db.str[tbl->s->db.length] == 0));
10666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438267 times.
10438267 assert(tbl->s->table_name.str[tbl->s->table_name.length] == 0);
10667
10668 10438267 m_data_size = Binary_log_event::TABLE_MAP_HEADER_LEN;
10669
2/4
✓ Branch 0 taken 10438431 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10438431 times.
10438267 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_source", m_data_size = 6;);
10670
10671 uchar dbuf[sizeof(m_dblen) + 1];
10672 uchar tbuf[sizeof(m_tbllen) + 1];
10673
1/2
✓ Branch 0 taken 10438030 times.
✗ Branch 1 not taken.
10438431 uchar *const dbuf_end = net_store_length(dbuf, (size_t)m_dblen);
10674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438030 times.
10438030 assert(static_cast<size_t>(dbuf_end - dbuf) <= sizeof(dbuf));
10675
1/2
✓ Branch 0 taken 10438275 times.
✗ Branch 1 not taken.
10438030 uchar *const tbuf_end = net_store_length(tbuf, (size_t)m_tbllen);
10676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438275 times.
10438275 assert(static_cast<size_t>(tbuf_end - tbuf) <= sizeof(tbuf));
10677
10678 10438275 m_data_size +=
10679 10438275 m_dblen + 1 + (dbuf_end - dbuf); // Include length and terminating \0
10680 10438275 m_data_size +=
10681 10438275 m_tbllen + 1 + (tbuf_end - tbuf); // Include length and terminating \0
10682
1/2
✓ Branch 0 taken 10438423 times.
✗ Branch 1 not taken.
10438275 cbuf_end = net_store_length(cbuf, (size_t)m_colcnt);
10683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438423 times.
10438423 assert(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf));
10684 10438423 m_data_size += (cbuf_end - cbuf) + m_colcnt; // COLCNT and column types
10685
10686
1/2
✓ Branch 0 taken 10438748 times.
✗ Branch 1 not taken.
10438423 m_coltype = (uchar *)my_malloc(key_memory_log_event, m_colcnt, MYF(MY_WME));
10687
10688
4/6
✓ Branch 0 taken 10438674 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 10438665 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10438674 times.
10438748 assert(m_colcnt ==
10689 this->m_fields.filtered_size() +
10690 DBUG_EVALUATE_IF("binlog_omit_last_column_from_table_map_event",
10691 -1, 0));
10692
10693
1/2
✓ Branch 0 taken 10438557 times.
✗ Branch 1 not taken.
10438674 for (auto it = this->m_fields.begin();
10694
7/12
✓ Branch 0 taken 45705792 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45705535 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 35266897 times.
✓ Branch 5 taken 10438638 times.
✓ Branch 6 taken 45705473 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 35266767 times.
✓ Branch 9 taken 10438774 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
80972483 it != this->m_fields.end() &&
10695
4/6
✓ Branch 0 taken 35266741 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 35266723 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
35266897 DBUG_EVALUATE_IF("binlog_omit_last_column_from_table_map_event",
10696 it.filtered_pos() != this->m_colcnt, true);
10697 35266767 ++it) {
10698
1/2
✓ Branch 0 taken 35266821 times.
✗ Branch 1 not taken.
35266767 Field *field = *it;
10699
2/4
✓ Branch 0 taken 35266632 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35267185 times.
✗ Branch 3 not taken.
35266821 m_coltype[it.filtered_pos()] = field->binlog_type();
10700 10438774 }
10701
3/4
✓ Branch 0 taken 10438565 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 10438564 times.
10438765 DBUG_EXECUTE_IF("inject_invalid_column_type", m_coltype[1] = 230;);
10702
10703 /*
10704 Calculate a bitmap for the results of maybe_null() for all columns.
10705 The bitmap is used to determine when there is a column from the master
10706 that is not on the slave and is null and thus not in the row data during
10707 replication.
10708 */
10709 10438565 uint num_null_bytes = (m_colcnt + 7) / 8;
10710 10438565 m_data_size += num_null_bytes;
10711 /*
10712 m_null_bits is a pointer indicating which columns can have a null value
10713 in a particular table.
10714 */
10715 10438698 m_null_bits =
10716
1/2
✓ Branch 0 taken 10438698 times.
✗ Branch 1 not taken.
10438565 (uchar *)my_malloc(key_memory_log_event, num_null_bytes, MYF(MY_WME));
10717
10718 10438756 m_field_metadata =
10719
1/2
✓ Branch 0 taken 10438756 times.
✗ Branch 1 not taken.
10438698 (uchar *)my_malloc(key_memory_log_event, (m_colcnt * 4), MYF(MY_WME));
10720 10438756 memset(m_field_metadata, 0, (m_colcnt * 4));
10721
10722 10438756 common_header->set_is_valid(m_null_bits != nullptr &&
10723
3/4
✓ Branch 0 taken 10438739 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 10438754 times.
✗ Branch 3 not taken.
20877510 m_field_metadata != nullptr &&
10724
2/2
✓ Branch 0 taken 10438736 times.
✓ Branch 1 taken 18 times.
10438754 m_coltype != nullptr);
10725 /*
10726 Create an array for the field metadata and store it.
10727 */
10728
1/2
✓ Branch 0 taken 10438677 times.
✗ Branch 1 not taken.
10438678 m_field_metadata_size = save_field_metadata();
10729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438677 times.
10438677 assert(m_field_metadata_size <= (m_colcnt * 4));
10730
10731 /*
10732 Now set the size of the data to the size of the field metadata array
10733 plus one or three bytes (see pack.c:net_store_length) for number of
10734 elements in the field metadata array.
10735 */
10736
2/2
✓ Branch 0 taken 10438658 times.
✓ Branch 1 taken 19 times.
10438677 if (m_field_metadata_size < 251)
10737 10438658 m_data_size += m_field_metadata_size + 1;
10738 else
10739 19 m_data_size += m_field_metadata_size + 3;
10740
10741 10438677 memset(m_null_bits, 0, num_null_bytes);
10742
1/2
✓ Branch 0 taken 10438553 times.
✗ Branch 1 not taken.
10438677 Bit_writer bit_writer{this->m_null_bits};
10743
8/14
✓ Branch 0 taken 10438805 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438750 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 35267292 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 35267283 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 45706054 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 45706034 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 35267282 times.
✓ Branch 13 taken 10438763 times.
45705668 for (auto field : this->m_fields) bit_writer.set(field->is_nullable());
10744 /*
10745 Marking event to require sequential execution in MTS
10746 if the query might have updated FK-referenced db.
10747 Unlike Query_log_event where this fact is encoded through
10748 the accessed db list in the Table_map case m_flags is exploited.
10749 */
10750 10438776 uchar dbs = thd_arg->get_binlog_accessed_db_names()
10751 738 ? thd_arg->get_binlog_accessed_db_names()->elements
10752
2/2
✓ Branch 0 taken 738 times.
✓ Branch 1 taken 10437769 times.
10439245 : 0;
10753
2/2
✓ Branch 0 taken 738 times.
✓ Branch 1 taken 10437769 times.
10438507 if (dbs == 1) {
10754 738 char *db_name = thd_arg->get_binlog_accessed_db_names()->head();
10755
1/2
✓ Branch 0 taken 738 times.
✗ Branch 1 not taken.
738 if (!strcmp(db_name, "")) m_flags |= TM_REFERRED_FK_DB_F;
10756 }
10757
10758
3/4
✓ Branch 0 taken 10438454 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 10438400 times.
10438507 if (table_has_generated_invisible_primary_key(m_table))
10759 54 m_flags |= TM_GENERATED_INVISIBLE_PK_F;
10760
10761
1/2
✓ Branch 0 taken 10438650 times.
✗ Branch 1 not taken.
10438454 init_metadata_fields();
10762 10438650 m_data_size += m_metadata_buf.length();
10763 10438644 }
10764 #endif /* defined(MYSQL_SERVER) */
10765
10766 /*
10767 Constructor used by slave to read the event from the binary log.
10768 */
10769 7636889 Table_map_log_event::Table_map_log_event(
10770 7636889 const char *buf, const Format_description_event *description_event)
10771 : binary_log::Table_map_event(buf, description_event),
10772 34423 Log_event(header(), footer())
10773 #ifdef MYSQL_SERVER
10774 ,
10775 7602466 m_table(nullptr),
10776
2/4
✓ Branch 0 taken 7602466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7602466 times.
✗ Branch 3 not taken.
7602466 m_fields(Replicated_columns_view::INBOUND)
10777 #endif
10778 {
10779
1/2
✓ Branch 0 taken 7636889 times.
✗ Branch 1 not taken.
7636889 DBUG_TRACE;
10780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7636889 times.
7636889 assert(header()->type_code == binary_log::TABLE_MAP_EVENT);
10781 7636889 }
10782
10783 51424486 Table_map_log_event::~Table_map_log_event() = default;
10784
10785 /*
10786 Return value is an error code, one of:
10787
10788 -1 Failure to open table [from open_tables()]
10789 0 Success
10790 1 No room for more tables [from set_table()]
10791 2 Out of memory [from set_table()]
10792 3 Wrong table definition
10793 4 Daisy-chaining RBR with SBR not possible
10794 */
10795
10796 #if defined(MYSQL_SERVER)
10797
10798 enum enum_tbl_map_status {
10799 /* no duplicate identifier found */
10800 OK_TO_PROCESS = 0,
10801
10802 /* this table map must be filtered out */
10803 FILTERED_OUT = 1,
10804
10805 /* identifier mapping table with different properties */
10806 SAME_ID_MAPPING_DIFFERENT_TABLE = 2,
10807
10808 /* a duplicate identifier was found mapping the same table */
10809 SAME_ID_MAPPING_SAME_TABLE = 3,
10810
10811 /*
10812 this table must be filtered out but found an active XA transaction. XA
10813 transactions shouldn't be used with replication filters, until disabling
10814 the XA read only optimization is a supported feature.
10815 */
10816 FILTERED_WITH_XA_ACTIVE = 4
10817 };
10818
10819 /*
10820 Checks if this table map event should be processed or not. First
10821 it checks the filtering rules, and then looks for duplicate identifiers
10822 in the existing list of rli->tables_to_lock.
10823
10824 It checks that there hasn't been any corruption by verifying that there
10825 are no duplicate entries with different properties.
10826
10827 In some cases, some binary logs could get corrupted, showing several
10828 tables mapped to the same table_id, 0 (see: BUG#56226). Thus we do this
10829 early sanity check for such cases and avoid that the server crashes
10830 later.
10831
10832 In some corner cases, the master logs duplicate table map events, i.e.,
10833 same id, same database name, same table name (see: BUG#37137). This is
10834 different from the above as it's the same table that is mapped again
10835 to the same identifier. Thus we cannot just check for same ids and
10836 assume that the event is corrupted we need to check every property.
10837
10838 NOTE: in the event that BUG#37137 ever gets fixed, this extra check
10839 will still be valid because we would need to support old binary
10840 logs anyway.
10841
10842 @param rli The relay log info reference.
10843 @param table_list A list element containing the table to check against.
10844 @return OK_TO_PROCESS
10845 if there was no identifier already in rli->tables_to_lock
10846
10847 FILTERED_OUT
10848 if the event is filtered according to the filtering rules
10849
10850 SAME_ID_MAPPING_DIFFERENT_TABLE
10851 if the same identifier already maps a different table in
10852 rli->tables_to_lock
10853
10854 SAME_ID_MAPPING_SAME_TABLE
10855 if the same identifier already maps the same table in
10856 rli->tables_to_lock.
10857 */
10858 290664 static enum_tbl_map_status check_table_map(Relay_log_info const *rli,
10859 RPL_TABLE_LIST *table_list) {
10860
1/2
✓ Branch 0 taken 290685 times.
✗ Branch 1 not taken.
290664 DBUG_TRACE;
10861 290685 enum_tbl_map_status res = OK_TO_PROCESS;
10862
10863
4/4
✓ Branch 0 taken 287929 times.
✓ Branch 1 taken 2756 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 290595 times.
578595 if (rli->info_thd->slave_thread /* filtering is for slave only */ &&
10864
3/4
✓ Branch 0 taken 287907 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 287896 times.
✓ Branch 3 taken 11 times.
287929 (!rli->rpl_filter->db_ok(table_list->db) ||
10865
3/4
✓ Branch 0 taken 287899 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 183 times.
✓ Branch 3 taken 287716 times.
287896 (rli->rpl_filter->is_on() &&
10866
3/4
✓ Branch 0 taken 183 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 123 times.
183 !rli->rpl_filter->tables_ok("", table_list))))
10867
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 67 times.
71 if (rli->info_thd->get_transaction()->xid_state()->has_state(
10868 XID_STATE::XA_ACTIVE))
10869 4 res = FILTERED_WITH_XA_ACTIVE;
10870 else
10871 67 res = FILTERED_OUT;
10872 else {
10873 290595 RPL_TABLE_LIST *ptr = static_cast<RPL_TABLE_LIST *>(rli->tables_to_lock);
10874
3/4
✓ Branch 0 taken 1372 times.
✓ Branch 1 taken 290546 times.
✓ Branch 2 taken 1372 times.
✗ Branch 3 not taken.
291918 for (uint i = 0; ptr && (i < rli->tables_to_lock_count);
10875 1323 ptr = static_cast<RPL_TABLE_LIST *>(ptr->next_local), i++) {
10876
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 1323 times.
1372 if (ptr->table_id == table_list->table_id) {
10877 147 if (strcmp(ptr->db, table_list->db) ||
10878
5/6
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 47 times.
96 strcmp(ptr->alias, table_list->table_name) ||
10879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 ptr->lock_descriptor().type !=
10880 TL_WRITE) // the ::do_apply_event always sets TL_WRITE
10881 2 res = SAME_ID_MAPPING_DIFFERENT_TABLE;
10882 else
10883 47 res = SAME_ID_MAPPING_SAME_TABLE;
10884
10885 49 break;
10886 }
10887 }
10888 }
10889
10890
3/8
✓ Branch 0 taken 290680 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 290680 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 290680 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
290666 DBUG_PRINT("debug", ("check of table map ended up with: %u", res));
10891
10892 290684 return res;
10893 290680 }
10894
10895 290675 int Table_map_log_event::do_apply_event(Relay_log_info const *rli) {
10896 RPL_TABLE_LIST *table_list;
10897 char *db_mem, *tname_mem;
10898 const char *ptr;
10899 size_t dummy_len;
10900 void *memory;
10901
1/2
✓ Branch 0 taken 290683 times.
✗ Branch 1 not taken.
290675 DBUG_TRACE;
10902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 290683 times.
290683 assert(rli->info_thd == thd);
10903
10904 /* Step the query id to mark what columns that are actually used. */
10905
1/2
✓ Branch 0 taken 290683 times.
✗ Branch 1 not taken.
290683 thd->set_query_id(next_query_id());
10906
10907 290681 if (!(memory =
10908
2/4
✓ Branch 0 taken 290681 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 290681 times.
290683 my_multi_malloc(key_memory_log_event, MYF(MY_WME), &table_list,
10909 sizeof(RPL_TABLE_LIST), &db_mem, (uint)NAME_LEN + 1,
10910 &tname_mem, (uint)NAME_LEN + 1, NullS)))
10911 return HA_ERR_OUT_OF_MEM;
10912
10913 290681 my_stpcpy(db_mem, m_dbnam.c_str());
10914 290679 my_stpcpy(tname_mem, m_tblnam.c_str());
10915
10916
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 290659 times.
290682 if (lower_case_table_names) {
10917
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 my_casedn_str(system_charset_info, db_mem);
10918
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
23 my_casedn_str(system_charset_info, tname_mem);
10919 }
10920
10921 /* rewrite rules changed the database */
10922
3/4
✓ Branch 0 taken 290680 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 290655 times.
581360 if (rli->rpl_filter != nullptr &&
10923
3/4
✓ Branch 0 taken 290680 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 290655 times.
290680 ((ptr = rli->rpl_filter->get_rewrite_db(db_mem, &dummy_len)) != db_mem)) {
10924 25 rli->rpl_filter->get_rewrite_db_statistics()->increase_counter();
10925 25 my_stpcpy(db_mem, ptr);
10926 }
10927
10928 290680 new (table_list) RPL_TABLE_LIST(db_mem, strlen(db_mem), tname_mem,
10929
1/2
✓ Branch 0 taken 290684 times.
✗ Branch 1 not taken.
290680 strlen(tname_mem), tname_mem, TL_WRITE);
10930
10931
3/4
✓ Branch 0 taken 290683 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 290671 times.
✓ Branch 3 taken 12 times.
290684 table_list->table_id = DBUG_EVALUATE_IF(
10932 "inject_tblmap_same_id_maps_diff_table", 0, m_table_id.id());
10933 290676 table_list->updating = true;
10934 290676 table_list->required_type = dd::enum_table_type::BASE_TABLE;
10935
3/8
✓ Branch 0 taken 290680 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 290681 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 290681 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
290676 DBUG_PRINT("debug", ("table: %s is mapped to %llu", table_list->table_name,
10936 table_list->table_id.id()));
10937
10938
1/2
✓ Branch 0 taken 290682 times.
✗ Branch 1 not taken.
290681 enum_tbl_map_status tblmap_status = check_table_map(rli, table_list);
10939
2/2
✓ Branch 0 taken 290561 times.
✓ Branch 1 taken 121 times.
290682 if (tblmap_status == OK_TO_PROCESS) {
10940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 290561 times.
290561 assert(thd->lex->query_tables != table_list);
10941
10942 /*
10943 Use placement new to construct the table_def instance in the
10944 memory allocated for it inside table_list.
10945
10946 The memory allocated by the table_def structure (i.e., not the
10947 memory allocated *for* the table_def structure) is released
10948 inside Relay_log_info::clear_tables_to_lock() by calling the
10949 table_def destructor explicitly.
10950 */
10951 290561 new (&table_list->m_tabledef)
10952 290560 table_def(m_coltype, m_colcnt, m_field_metadata, m_field_metadata_size,
10953
1/2
✓ Branch 0 taken 290558 times.
✗ Branch 1 not taken.
290561 m_null_bits, m_flags);
10954
10955 290558 table_list->m_tabledef_valid = true;
10956 290558 table_list->m_conv_table = nullptr;
10957 290558 table_list->open_type = OT_BASE_ONLY;
10958
10959 /*
10960 We record in the slave's information that the table should be
10961 locked by linking the table into the list of tables to lock.
10962 */
10963 290558 table_list->next_global = table_list->next_local = rli->tables_to_lock;
10964 290558 const_cast<Relay_log_info *>(rli)->tables_to_lock = table_list;
10965 290558 const_cast<Relay_log_info *>(rli)->tables_to_lock_count++;
10966 /* 'memory' is freed in clear_tables_to_lock */
10967 } else // FILTERED_OUT, SAME_ID_MAPPING_*
10968 {
10969
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 117 times.
121 if (tblmap_status == FILTERED_WITH_XA_ACTIVE) {
10970
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (thd->slave_thread)
10971
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 rli->report(ERROR_LEVEL, ER_XA_REPLICATION_FILTERS, "%s",
10972
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 ER_THD(thd, ER_XA_REPLICATION_FILTERS));
10973 else
10974 /*
10975 For the cases in which a 'BINLOG' statement is set to
10976 execute in a user session
10977 */
10978 my_printf_error(ER_XA_REPLICATION_FILTERS, "%s", MYF(0),
10979 ER_THD(thd, ER_XA_REPLICATION_FILTERS));
10980 }
10981 /*
10982 If mapped already but with different properties, we raise an
10983 error.
10984 If mapped already but with same properties we skip the event.
10985 If filtered out we skip the event.
10986
10987 In all three cases, we need to free the memory previously
10988 allocated.
10989 */
10990
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 115 times.
117 else if (tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE) {
10991 /*
10992 Something bad has happened. We need to stop the slave as strange things
10993 could happen if we proceed: slave crash, wrong table being updated, ...
10994 As a consequence we push an error in this case.
10995 */
10996
10997 char buf[256];
10998
10999 4 snprintf(buf, sizeof(buf),
11000 "Found table map event mapping table id %llu which "
11001 "was already mapped but with different settings.",
11002 2 table_list->table_id.id());
11003
11004
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (thd->slave_thread)
11005
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
11006
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ER_THD(thd, ER_SLAVE_FATAL_ERROR), buf);
11007 else
11008 /*
11009 For the cases in which a 'BINLOG' statement is set to
11010 execute in a user session
11011 */
11012
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_BINLOG_FATAL_ERROR,
11013
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ER_THD(thd, ER_BINLOG_FATAL_ERROR), MYF(0), buf);
11014 }
11015
11016
1/2
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
121 my_free(memory);
11017 }
11018
11019 290662 return tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE;
11020 290662 }
11021
11022 288092 Log_event::enum_skip_reason Table_map_log_event::do_shall_skip(
11023 Relay_log_info *rli) {
11024 /*
11025 If the slave skip counter is 1, then we should not start executing
11026 on the next event.
11027 */
11028 288092 return continue_group(rli);
11029 }
11030
11031 446 int Table_map_log_event::do_update_pos(Relay_log_info *rli) {
11032 446 rli->inc_event_relay_log_pos();
11033 446 return 0;
11034 }
11035
11036 10438527 bool Table_map_log_event::write_data_header(Basic_ostream *ostream) {
11037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438579 times.
10438527 assert(m_table_id.is_valid());
11038 uchar buf[Binary_log_event::TABLE_MAP_HEADER_LEN];
11039
2/6
✓ Branch 0 taken 10438560 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10438560 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
10438579 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_source", {
11040 int4store(buf + 0, static_cast<uint32>(m_table_id.id()));
11041 int2store(buf + 4, m_flags);
11042 return (wrapper_my_b_safe_write(ostream, buf, 6));
11043 });
11044 10438560 int6store(buf + TM_MAPID_OFFSET, m_table_id.id());
11045 10438252 int2store(buf + TM_FLAGS_OFFSET, m_flags);
11046
1/2
✓ Branch 0 taken 10438714 times.
✗ Branch 1 not taken.
10438369 return (wrapper_my_b_safe_write(ostream, buf,
11047 10438714 Binary_log_event::TABLE_MAP_HEADER_LEN));
11048 }
11049
11050 10438622 bool Table_map_log_event::write_data_body(Basic_ostream *ostream) {
11051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438562 times.
10438622 assert(!m_dbnam.empty());
11052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438607 times.
10438562 assert(!m_tblnam.empty());
11053
11054 uchar dbuf[sizeof(m_dblen) + 1];
11055
1/2
✓ Branch 0 taken 10438612 times.
✗ Branch 1 not taken.
10438607 uchar *const dbuf_end = net_store_length(dbuf, (size_t)m_dblen);
11056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438612 times.
10438612 assert(static_cast<size_t>(dbuf_end - dbuf) <= sizeof(dbuf));
11057
11058 uchar tbuf[sizeof(m_tbllen) + 1];
11059
1/2
✓ Branch 0 taken 10438659 times.
✗ Branch 1 not taken.
10438612 uchar *const tbuf_end = net_store_length(tbuf, (size_t)m_tbllen);
11060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438659 times.
10438659 assert(static_cast<size_t>(tbuf_end - tbuf) <= sizeof(tbuf));
11061
11062 uchar cbuf[sizeof(m_colcnt) + 1];
11063
1/2
✓ Branch 0 taken 10438702 times.
✗ Branch 1 not taken.
10438659 uchar *const cbuf_end = net_store_length(cbuf, (size_t)m_colcnt);
11064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438702 times.
10438702 assert(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf));
11065
11066 /*
11067 Store the size of the field metadata.
11068 */
11069 uchar mbuf[2 * sizeof(m_field_metadata_size)];
11070
1/2
✓ Branch 0 taken 10438731 times.
✗ Branch 1 not taken.
10438702 uchar *const mbuf_end = net_store_length(mbuf, m_field_metadata_size);
11071
11072
1/2
✓ Branch 0 taken 10438735 times.
✗ Branch 1 not taken.
10438731 return (wrapper_my_b_safe_write(ostream, dbuf, (size_t)(dbuf_end - dbuf)) ||
11073
2/4
✓ Branch 0 taken 10438751 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438757 times.
✗ Branch 3 not taken.
10438652 wrapper_my_b_safe_write(ostream, (const uchar *)m_dbnam.c_str(),
11074 10438702 m_dblen + 1) ||
11075
2/4
✓ Branch 0 taken 10438740 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438740 times.
✗ Branch 3 not taken.
10438757 wrapper_my_b_safe_write(ostream, tbuf, (size_t)(tbuf_end - tbuf)) ||
11076
2/4
✓ Branch 0 taken 10438784 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438784 times.
✗ Branch 3 not taken.
10438736 wrapper_my_b_safe_write(ostream, (const uchar *)m_tblnam.c_str(),
11077 10438740 m_tbllen + 1) ||
11078
3/4
✓ Branch 0 taken 10438784 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438753 times.
✓ Branch 3 taken 31 times.
10438784 wrapper_my_b_safe_write(ostream, cbuf, (size_t)(cbuf_end - cbuf)) ||
11079
2/4
✓ Branch 0 taken 10438783 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438785 times.
✗ Branch 3 not taken.
10438753 wrapper_my_b_safe_write(ostream, m_coltype, m_colcnt) ||
11080
2/4
✓ Branch 0 taken 10438788 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438789 times.
✗ Branch 3 not taken.
10438785 wrapper_my_b_safe_write(ostream, mbuf, (size_t)(mbuf_end - mbuf)) ||
11081
2/4
✓ Branch 0 taken 10438726 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438727 times.
✗ Branch 3 not taken.
10438789 wrapper_my_b_safe_write(ostream, m_field_metadata,
11082 10438775 m_field_metadata_size) ||
11083
5/6
✓ Branch 0 taken 10438702 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 10438775 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10438774 times.
✓ Branch 5 taken 1 times.
31316199 wrapper_my_b_safe_write(ostream, m_null_bits, (m_colcnt + 7) / 8) ||
11084
2/4
✓ Branch 0 taken 10438716 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10438771 times.
10438774 wrapper_my_b_safe_write(ostream, (const uchar *)m_metadata_buf.ptr(),
11085 10438771 m_metadata_buf.length()));
11086 }
11087
11088 /**
11089 stores an integer into packed format.
11090
11091 @param[out] str_buf a buffer where the packed integer will be stored.
11092 @param[in] length the integer will be packed.
11093 */
11094 26426937 static inline void store_compressed_length(String &str_buf, ulonglong length) {
11095 // Store Type and packed length
11096 uchar buf[16];
11097
1/2
✓ Branch 0 taken 26427210 times.
✗ Branch 1 not taken.
26426937 uchar *buf_ptr = net_store_length(buf, length);
11098
11099
1/2
✓ Branch 0 taken 26427389 times.
✗ Branch 1 not taken.
26427210 str_buf.append(reinterpret_cast<char *>(buf), buf_ptr - buf);
11100 26427389 }
11101
11102 /**
11103 Write data into str_buf with Type|Length|Value(TLV) format.
11104
11105 @param[out] str_buf a buffer where the field is stored.
11106 @param[in] type type of the field
11107 @param[in] length length of the field value
11108 @param[in] value value of the field
11109 */
11110 18104314 static inline bool write_tlv_field(
11111 String &str_buf,
11112 enum Table_map_log_event::Optional_metadata_field_type type, uint length,
11113 const uchar *value) {
11114 /* type is stored in one byte, so it should never bigger than 255. */
11115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18104314 times.
18104314 assert(static_cast<int>(type) <= 255);
11116 18104314 str_buf.append((char)type);
11117 18104741 store_compressed_length(str_buf, length);
11118 18104842 return str_buf.append(reinterpret_cast<const char *>(value), length);
11119 }
11120
11121 /**
11122 Write data into str_buf with Type|Length|Value(TLV) format.
11123
11124 @param[out] str_buf a buffer where the field is stored.
11125 @param[in] type type of the field
11126 @param[in] value value of the field
11127 */
11128 18104440 static inline bool write_tlv_field(
11129 String &str_buf,
11130 enum Table_map_log_event::Optional_metadata_field_type type,
11131 const String &value) {
11132 18104459 return write_tlv_field(str_buf, type, value.length(),
11133 36209594 reinterpret_cast<const uchar *>(value.ptr()));
11134 }
11135 #endif // MYSQL_SERVER
11136
11137 64767042 static inline bool is_character_type(uint type) {
11138
2/2
✓ Branch 0 taken 27619890 times.
✓ Branch 1 taken 37147152 times.
64767042 switch (type) {
11139 27619890 case MYSQL_TYPE_STRING:
11140 case MYSQL_TYPE_VAR_STRING:
11141 case MYSQL_TYPE_VARCHAR:
11142 case MYSQL_TYPE_BLOB:
11143 27619890 return true;
11144 37147152 default:
11145 37147152 return false;
11146 }
11147 }
11148
11149 290 static inline bool is_enum_or_set_type(uint type) {
11150
4/4
✓ Branch 0 taken 251 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 212 times.
290 return type == MYSQL_TYPE_ENUM || type == MYSQL_TYPE_SET;
11151 }
11152
11153 #ifdef MYSQL_SERVER
11154 35266536 static inline bool is_numeric_field(const Field *field) {
11155 35266536 return has_signedess_information_type(field->binlog_type());
11156 }
11157
11158 64766556 static inline bool is_character_field(const Field *field) {
11159 64766556 return is_character_type(field->real_type());
11160 }
11161
11162 81 static inline bool is_enum_field(const Field *field) {
11163 81 return field->real_type() == MYSQL_TYPE_ENUM;
11164 }
11165
11166 81 static inline bool is_set_field(const Field *field) {
11167 81 return field->real_type() == MYSQL_TYPE_SET;
11168 }
11169
11170 101 static inline bool is_enum_or_set_field(const Field *field) {
11171 101 return is_enum_or_set_type(field->real_type());
11172 }
11173
11174 35266872 static inline bool is_geometry_field(const Field *field) {
11175 35266872 return field->real_type() == MYSQL_TYPE_GEOMETRY;
11176 }
11177
11178 10438001 void Table_map_log_event::init_metadata_fields() {
11179
1/2
✓ Branch 0 taken 10438580 times.
✗ Branch 1 not taken.
10438001 DBUG_TRACE;
11180
3/4
✓ Branch 0 taken 10438452 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 10438451 times.
10438580 DBUG_EXECUTE_IF("simulate_no_optional_metadata", return;);
11181
11182 52191422 if (init_signedness_field() ||
11183
5/8
✓ Branch 0 taken 10438264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438038 times.
✓ Branch 3 taken 226 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 10438477 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
20876293 init_charset_field(&is_character_field, DEFAULT_CHARSET,
11184
3/6
✓ Branch 0 taken 10437940 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438067 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10438369 times.
✗ Branch 5 not taken.
20876804 COLUMN_CHARSET) ||
11185
2/4
✓ Branch 0 taken 10438127 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10438225 times.
10438038 init_geometry_type_field()) {
11186 1 m_metadata_buf.length(0);
11187 1 return;
11188 }
11189
11190
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 10438459 times.
10438477 if (binlog_row_metadata == BINLOG_ROW_METADATA_FULL) {
11191
3/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
18 if (DBUG_EVALUATE_IF("dont_log_column_name", 0, init_column_name_field()) ||
11192
4/8
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
36 init_charset_field(&is_enum_or_set_field, ENUM_AND_SET_DEFAULT_CHARSET,
11193 18 ENUM_AND_SET_COLUMN_CHARSET) ||
11194
4/8
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
18 init_set_str_value_field() || init_enum_str_value_field() ||
11195
8/14
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 17 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 17 times.
✓ Branch 12 taken 18 times.
✗ Branch 13 not taken.
54 init_primary_key_field() || init_column_visibility_field()) {
11196 1 m_metadata_buf.length(0);
11197 }
11198 }
11199
1/2
✓ Branch 0 taken 10438660 times.
✗ Branch 1 not taken.
10437933 }
11200
11201 10438301 bool Table_map_log_event::init_signedness_field() {
11202 /* use it to store signed flags, each numeric column take a bit. */
11203 10438301 StringBuffer<128> buf;
11204 10438468 unsigned char flag = 0;
11205 10438468 unsigned char mask = 0x80;
11206
11207
8/14
✓ Branch 0 taken 10438781 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438783 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 35267246 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 35267240 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 45705616 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 45705915 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 35267184 times.
✓ Branch 13 taken 10438716 times.
45705079 for (auto field : this->m_fields) {
11208
3/4
✓ Branch 0 taken 35266745 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20884110 times.
✓ Branch 3 taken 14382635 times.
35267246 if (is_numeric_field(field)) {
11209
1/2
✓ Branch 0 taken 20884190 times.
✗ Branch 1 not taken.
20884110 Field_num *field_num = dynamic_cast<Field_num *>(field);
11210
2/2
✓ Branch 0 taken 1032068 times.
✓ Branch 1 taken 19851908 times.
20884110 if (field_num->is_unsigned()) flag |= mask;
11211
11212 20883976 mask >>= 1;
11213
11214 // 8 fields are tested, store the result and clear the flag.
11215
2/2
✓ Branch 0 taken 291285 times.
✓ Branch 1 taken 20592691 times.
20883976 if (mask == 0) {
11216
1/2
✓ Branch 0 taken 291285 times.
✗ Branch 1 not taken.
291285 buf.append(flag);
11217 291285 flag = 0;
11218 291285 mask = 0x80;
11219 }
11220 }
11221 10438716 }
11222
11223 // Stores the signedness flags of last few columns
11224
3/4
✓ Branch 0 taken 10071271 times.
✓ Branch 1 taken 367434 times.
✓ Branch 2 taken 10070732 times.
✗ Branch 3 not taken.
10438705 if (mask != 0x80) buf.append(flag);
11225
11226 // The table has no numeric column, so don't log SIGNEDNESS field
11227
2/2
✓ Branch 0 taken 300444 times.
✓ Branch 1 taken 10137776 times.
10438166 if (buf.is_empty()) return false;
11228
11229
1/2
✓ Branch 0 taken 10138231 times.
✗ Branch 1 not taken.
10137776 return write_tlv_field(m_metadata_buf, SIGNEDNESS, buf);
11230 10438675 }
11231
11232 10437973 bool Table_map_log_event::init_charset_field(
11233 std::function<bool(const Field *)> include_type,
11234 Optional_metadata_field_type default_charset_type,
11235 Optional_metadata_field_type column_charset_type) {
11236
3/4
✓ Branch 0 taken 10438178 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 10438177 times.
10437973 DBUG_EXECUTE_IF("simulate_init_charset_field_error", return true;);
11237
11238 10438177 std::map<uint, uint> collation_map;
11239 // For counting characters columns
11240 10438474 uint char_col_cnt = 0;
11241
11242 /* Find the collation number used by most fields */
11243
8/14
✓ Branch 0 taken 10438797 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438790 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 35267109 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 35267304 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 45705525 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 45705858 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 35267041 times.
✓ Branch 13 taken 10438684 times.
45705607 for (auto field : this->m_fields) {
11244
3/4
✓ Branch 0 taken 35267131 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13809970 times.
✓ Branch 3 taken 21457161 times.
35267109 if (include_type(field)) {
11245
2/2
✓ Branch 0 taken 13809968 times.
✓ Branch 1 taken 2 times.
13809970 Field_str *field_str = dynamic_cast<Field_str *>(field);
11246
11247
2/4
✓ Branch 0 taken 13809975 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13809972 times.
✗ Branch 3 not taken.
13809970 collation_map[field_str->charset()->number]++;
11248 13809972 char_col_cnt++;
11249 }
11250 10438684 }
11251
11252
2/2
✓ Branch 0 taken 2735575 times.
✓ Branch 1 taken 7703198 times.
10438773 if (char_col_cnt == 0) return false;
11253
11254 /* Find the most used collation */
11255 7703198 uint most_used_collation = 0;
11256 7703198 uint most_used_count = 0;
11257 7703198 for (std::map<uint, uint>::iterator it = collation_map.begin();
11258
2/2
✓ Branch 0 taken 7929243 times.
✓ Branch 1 taken 7703195 times.
15632441 it != collation_map.end(); it++) {
11259
2/2
✓ Branch 0 taken 7738596 times.
✓ Branch 1 taken 190647 times.
7929243 if (it->second > most_used_count) {
11260 7738596 most_used_count = it->second;
11261 7738596 most_used_collation = it->first;
11262 }
11263 }
11264
11265 /*
11266 Comparing length of COLUMN_CHARSET field and COLUMN_CHARSET_WITH_DEFAULT
11267 field to decide which field should be logged.
11268
11269 Length of COLUMN_CHARSET = character column count * collation id size.
11270 Length of COLUMN_CHARSET_WITH_DEFAULT =
11271 default collation_id size + count of columns not use default charset *
11272 (column index size + collation id size)
11273
11274 Assume column index just uses 1 byte and collation number also uses 1 byte.
11275 */
11276
2/2
✓ Branch 0 taken 163578 times.
✓ Branch 1 taken 7539617 times.
7703195 if (char_col_cnt * 1 < (1 + (char_col_cnt - most_used_count) * 2)) {
11277 163578 StringBuffer<512> buf;
11278
11279 /*
11280 Stores character set information into COLUMN_CHARSET format,
11281 character sets of all columns are stored one by one.
11282 -----------------------------------------
11283 | Charset number | .... |Charset number |
11284 -----------------------------------------
11285 */
11286
8/14
✓ Branch 0 taken 163578 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 163578 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 671264 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 671264 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 834842 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 834842 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 671264 times.
✓ Branch 13 taken 163578 times.
834842 for (auto field : this->m_fields) {
11287
3/4
✓ Branch 0 taken 671264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 336330 times.
✓ Branch 3 taken 334934 times.
671264 if (include_type(field)) {
11288
1/2
✓ Branch 0 taken 336330 times.
✗ Branch 1 not taken.
336330 Field_str *field_str = dynamic_cast<Field_str *>(field);
11289
11290
2/4
✓ Branch 0 taken 336330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 336330 times.
✗ Branch 3 not taken.
336330 store_compressed_length(buf, field_str->charset()->number);
11291 }
11292 163578 }
11293
1/2
✓ Branch 0 taken 163578 times.
✗ Branch 1 not taken.
163578 return write_tlv_field(m_metadata_buf, column_charset_type, buf);
11294 163578 } else {
11295 7539617 StringBuffer<512> buf;
11296 7539615 uint char_column_index = 0;
11297 7539615 uint default_collation = most_used_collation;
11298
11299 /*
11300 Stores character set information into DEFAULT_CHARSET format,
11301 First stores the default character set, and then stores the character
11302 sets different to default character with their column index one by one.
11303 --------------------------------------------------------
11304 | Default Charset | Col Index | Charset number | ... |
11305 --------------------------------------------------------
11306 */
11307
11308 // Store the default collation number
11309
1/2
✓ Branch 0 taken 7539620 times.
✗ Branch 1 not taken.
7539615 store_compressed_length(buf, default_collation);
11310
11311
8/14
✓ Branch 0 taken 7539620 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7539619 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28828731 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 28828734 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 36368351 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 36368352 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 28828731 times.
✓ Branch 13 taken 7539617 times.
36368351 for (auto field : this->m_fields) {
11312
3/4
✓ Branch 0 taken 28828724 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13473638 times.
✓ Branch 3 taken 15355086 times.
28828731 if (include_type(field)) {
11313
1/2
✓ Branch 0 taken 13473638 times.
✗ Branch 1 not taken.
13473638 Field_str *field_str = dynamic_cast<Field_str *>(field);
11314
11315
3/4
✓ Branch 0 taken 13473649 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85322 times.
✓ Branch 3 taken 13388327 times.
13473638 if (field_str->charset()->number != default_collation) {
11316
1/2
✓ Branch 0 taken 85322 times.
✗ Branch 1 not taken.
85322 store_compressed_length(buf, char_column_index);
11317
2/4
✓ Branch 0 taken 85322 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85318 times.
✗ Branch 3 not taken.
85322 store_compressed_length(buf, field_str->charset()->number);
11318 }
11319 13473645 char_column_index++;
11320 }
11321 7539617 }
11322
1/2
✓ Branch 0 taken 7539620 times.
✗ Branch 1 not taken.
7539620 return write_tlv_field(m_metadata_buf, default_charset_type, buf);
11323 7539620 }
11324 10438768 }
11325
11326 17 bool Table_map_log_event::init_column_name_field() {
11327 17 StringBuffer<2048> buf;
11328
11329
8/14
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 77 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 77 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 94 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 94 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 77 times.
✓ Branch 13 taken 17 times.
94 for (auto field : this->m_fields) {
11330 77 size_t len = strlen(field->field_name);
11331
11332
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 store_compressed_length(buf, len);
11333
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 buf.append(field->field_name, len);
11334 17 }
11335
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
34 return write_tlv_field(m_metadata_buf, COLUMN_NAME, buf);
11336 17 }
11337
11338 18 bool Table_map_log_event::init_set_str_value_field() {
11339 18 StringBuffer<1024> buf;
11340
11341 /*
11342 SET string values are stored in the same format:
11343 ----------------------------------------------
11344 | Value number | value1 len | value 1| .... | // first SET column
11345 ----------------------------------------------
11346 | Value number | value1 len | value 1| .... | // second SET column
11347 ----------------------------------------------
11348 */
11349
8/14
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 81 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 81 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 99 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 99 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 81 times.
✓ Branch 13 taken 18 times.
99 for (auto field : this->m_fields) {
11350
3/4
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 74 times.
81 if (is_set_field(field)) {
11351
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 TYPELIB *typelib = dynamic_cast<Field_set *>(field)->typelib;
11352
11353
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 store_compressed_length(buf, typelib->count);
11354
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 7 times.
28 for (unsigned int i = 0; i < typelib->count; i++) {
11355
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 store_compressed_length(buf, typelib->type_lengths[i]);
11356
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 buf.append(typelib->type_names[i], typelib->type_lengths[i]);
11357 }
11358 }
11359 18 }
11360
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16 times.
18 if (buf.length() > 0)
11361
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return write_tlv_field(m_metadata_buf, SET_STR_VALUE, buf);
11362 16 return false;
11363 18 }
11364
11365 18 bool Table_map_log_event::init_enum_str_value_field() {
11366 18 StringBuffer<1024> buf;
11367
11368 /* ENUM is same to SET columns, see comment in init_set_str_value_field */
11369
8/14
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 81 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 81 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 99 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 99 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 81 times.
✓ Branch 13 taken 18 times.
99 for (auto field : this->m_fields) {
11370
3/4
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 74 times.
81 if (is_enum_field(field)) {
11371
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 TYPELIB *typelib = dynamic_cast<Field_enum *>(field)->typelib;
11372
11373
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 store_compressed_length(buf, typelib->count);
11374
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 7 times.
28 for (unsigned int i = 0; i < typelib->count; i++) {
11375
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 store_compressed_length(buf, typelib->type_lengths[i]);
11376
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 buf.append(typelib->type_names[i], typelib->type_lengths[i]);
11377 }
11378 }
11379 18 }
11380
11381
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16 times.
18 if (buf.length() > 0)
11382
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return write_tlv_field(m_metadata_buf, ENUM_STR_VALUE, buf);
11383 16 return false;
11384 18 }
11385
11386 10437749 bool Table_map_log_event::init_geometry_type_field() {
11387 10437749 StringBuffer<256> buf;
11388
11389 /* Geometry type of geometry columns is stored one by one as packed length */
11390
8/14
✓ Branch 0 taken 10438777 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10438764 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 35267225 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 35267221 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 45705568 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 45705777 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 35267083 times.
✓ Branch 13 taken 10438759 times.
45705346 for (auto field : this->m_fields) {
11391
3/4
✓ Branch 0 taken 35267102 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 275873 times.
✓ Branch 3 taken 34991229 times.
35267225 if (is_geometry_field(field)) {
11392
1/2
✓ Branch 0 taken 275873 times.
✗ Branch 1 not taken.
275873 int type = dynamic_cast<Field_geom *>(field)->geom_type;
11393
3/4
✓ Branch 0 taken 275873 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 275870 times.
275873 DBUG_EXECUTE_IF("inject_invalid_geometry_type", type = 100;);
11394
1/2
✓ Branch 0 taken 275873 times.
✗ Branch 1 not taken.
275873 store_compressed_length(buf, type);
11395 }
11396 10438759 }
11397
11398
2/2
✓ Branch 0 taken 263620 times.
✓ Branch 1 taken 10175079 times.
10438694 if (buf.length() > 0)
11399
1/2
✓ Branch 0 taken 263620 times.
✗ Branch 1 not taken.
263620 return write_tlv_field(m_metadata_buf, GEOMETRY_TYPE, buf);
11400 10175079 return false;
11401 10438699 }
11402
11403 18 bool Table_map_log_event::init_primary_key_field() {
11404
3/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 17 times.
18 DBUG_EXECUTE_IF("simulate_init_primary_key_field_error", return true;);
11405
11406
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4 times.
17 if (unlikely(m_table->s->is_missing_primary_key())) return false;
11407
11408 // If any key column uses prefix like KEY(c1(10)) */
11409 4 bool has_prefix = false;
11410 4 KEY *pk = m_table->key_info + m_table->s->primary_key;
11411
11412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(pk->user_defined_key_parts > 0);
11413
11414 /* Check if any key column uses prefix */
11415
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (uint i = 0; i < pk->user_defined_key_parts; i++) {
11416 6 KEY_PART_INFO *key_part = pk->key_part + i;
11417 12 if (key_part->length !=
11418
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
6 m_table->field[key_part->fieldnr - 1]->key_length()) {
11419 2 has_prefix = true;
11420 2 break;
11421 }
11422 }
11423
11424 4 StringBuffer<128> buf;
11425
11426
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!has_prefix) {
11427 /* Index of PK columns are stored one by one. */
11428
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (uint i = 0; i < pk->user_defined_key_parts; i++) {
11429 4 KEY_PART_INFO *key_part = pk->key_part + i;
11430
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 store_compressed_length(buf, key_part->fieldnr - 1);
11431 }
11432
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return write_tlv_field(m_metadata_buf, SIMPLE_PRIMARY_KEY, buf);
11433 } else {
11434 /* Index of PK columns are stored with a prefix length one by one. */
11435
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (uint i = 0; i < pk->user_defined_key_parts; i++) {
11436 6 KEY_PART_INFO *key_part = pk->key_part + i;
11437 6 size_t prefix = 0;
11438
11439
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 store_compressed_length(buf, key_part->fieldnr - 1);
11440
11441 // Store character length but not octet length
11442 12 if (key_part->length !=
11443
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
6 m_table->field[key_part->fieldnr - 1]->key_length())
11444
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 prefix = key_part->length / key_part->field->charset()->mbmaxlen;
11445
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 store_compressed_length(buf, prefix);
11446 }
11447
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return write_tlv_field(m_metadata_buf, PRIMARY_KEY_WITH_PREFIX, buf);
11448 }
11449 4 }
11450
11451 17 bool Table_map_log_event::init_column_visibility_field() {
11452 /*
11453 Buffer to store column visibility. Each column take a bit. Bit is set if
11454 column is visible.
11455 */
11456 17 StringBuffer<128> buf;
11457 17 unsigned char flags = 0;
11458 17 unsigned char mask = 0x80;
11459
11460
8/14
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 80 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 80 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 97 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 97 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 80 times.
✓ Branch 13 taken 17 times.
97 for (auto field : this->m_fields) {
11461
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 7 times.
80 if (!field->is_hidden_by_user()) flags |= mask;
11462 80 mask >>= 1;
11463
11464 // 8 columns are tested. Store the result and clear the flag.
11465
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 77 times.
80 if (mask == 0) {
11466
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 buf.append(flags);
11467 3 flags = 0;
11468 3 mask = 0x80;
11469 }
11470 17 }
11471
11472 // Store the flag for last few columns.
11473
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
17 if (mask != 0x80) buf.append(flags);
11474
11475
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
34 return write_tlv_field(m_metadata_buf, COLUMN_VISIBILITY, buf);
11476 17 }
11477
11478 /*
11479 Print some useful information for the SHOW BINARY LOG information
11480 field.
11481 */
11482
11483 34920 int Table_map_log_event::pack_info(Protocol *protocol) {
11484 char buf[256];
11485 34920 size_t bytes = snprintf(buf, sizeof(buf), "table_id: %llu (%s.%s)",
11486 34920 m_table_id.id(), m_dbnam.c_str(), m_tblnam.c_str());
11487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34920 times.
34920 assert(bytes < 256);
11488
1/2
✓ Branch 0 taken 34920 times.
✗ Branch 1 not taken.
34920 protocol->store_string(buf, bytes, &my_charset_bin);
11489 34920 return 0;
11490 }
11491 #endif // MYSQL_SERVER
11492
11493 #ifndef MYSQL_SERVER
11494 29921 void Table_map_log_event::print(FILE *,
11495 PRINT_EVENT_INFO *print_event_info) const {
11496
2/2
✓ Branch 0 taken 29919 times.
✓ Branch 1 taken 2 times.
29921 if (!print_event_info->short_form) {
11497 29919 print_header(&print_event_info->head_cache, print_event_info, true);
11498 29919 my_b_printf(&print_event_info->head_cache,
11499 "\tTable_map: `%s`.`%s` mapped to number %llu\n",
11500 m_dbnam.c_str(), m_tblnam.c_str(), m_table_id.id());
11501
11502
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 29882 times.
29919 if (print_event_info->print_table_metadata) {
11503 37 Optional_metadata_fields fields(m_optional_metadata,
11504
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 m_optional_metadata_len);
11505
11506
3/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
37 if (m_optional_metadata) assert(fields.is_valid);
11507
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 print_columns(&print_event_info->head_cache, fields);
11508
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 print_primary_key(&print_event_info->head_cache, fields);
11509 37 }
11510
11511 29919 print_base64(&print_event_info->body_cache, print_event_info, true);
11512 }
11513 29921 }
11514
11515 /**
11516 return the string name of a type.
11517
11518 @param[in] type type of a column
11519 @param[in,out] meta_ptr the meta_ptr of the column. If the type doesn't have
11520 metadata, it will not change meta_ptr, otherwise
11521 meta_ptr will be moved to the end of the column's
11522 metadat.
11523 @param[in] cs charset of the column if it is a character column.
11524 @param[out] typestr buffer to storing the string name of the type
11525 @param[in] typestr_length length of typestr
11526 @param[in] geometry_type internal geometry_type
11527 */
11528 177 static void get_type_name(uint type, unsigned char **meta_ptr,
11529 const CHARSET_INFO *cs, char *typestr,
11530 uint typestr_length, unsigned int geometry_type) {
11531
22/23
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 2 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 2 times.
✓ Branch 15 taken 17 times.
✓ Branch 16 taken 17 times.
✓ Branch 17 taken 16 times.
✓ Branch 18 taken 10 times.
✓ Branch 19 taken 21 times.
✓ Branch 20 taken 1 times.
✓ Branch 21 taken 25 times.
✓ Branch 22 taken 1 times.
177 switch (type) {
11532 41 case MYSQL_TYPE_LONG:
11533 41 snprintf(typestr, typestr_length, "%s", "INT");
11534 41 break;
11535 case MYSQL_TYPE_BOOL:
11536 snprintf(typestr, typestr_length, "BOOLEAN");
11537 break;
11538 3 case MYSQL_TYPE_TINY:
11539 3 snprintf(typestr, typestr_length, "TINYINT");
11540 3 break;
11541 2 case MYSQL_TYPE_SHORT:
11542 2 snprintf(typestr, typestr_length, "SMALLINT");
11543 2 break;
11544 2 case MYSQL_TYPE_INT24:
11545 2 snprintf(typestr, typestr_length, "MEDIUMINT");
11546 2 break;
11547 3 case MYSQL_TYPE_LONGLONG:
11548 3 snprintf(typestr, typestr_length, "BIGINT");
11549 3 break;
11550 2 case MYSQL_TYPE_NEWDECIMAL:
11551 2 snprintf(typestr, typestr_length, "DECIMAL(%d,%d)", (*meta_ptr)[0],
11552 2 (*meta_ptr)[1]);
11553 2 (*meta_ptr) += 2;
11554 2 break;
11555 3 case MYSQL_TYPE_FLOAT:
11556 3 snprintf(typestr, typestr_length, "FLOAT");
11557 3 (*meta_ptr)++;
11558 3 break;
11559 2 case MYSQL_TYPE_DOUBLE:
11560 2 snprintf(typestr, typestr_length, "DOUBLE");
11561 2 (*meta_ptr)++;
11562 2 break;
11563 2 case MYSQL_TYPE_BIT:
11564 2 snprintf(typestr, typestr_length, "BIT(%d)",
11565 2 (((*meta_ptr)[0])) + (*meta_ptr)[1] * 8);
11566 2 (*meta_ptr) += 2;
11567 2 break;
11568 2 case MYSQL_TYPE_TIMESTAMP2:
11569
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (**meta_ptr != 0)
11570 1 snprintf(typestr, typestr_length, "TIMESTAMP(%d)", **meta_ptr);
11571 else
11572 1 snprintf(typestr, typestr_length, "TIMESTAMP");
11573 2 (*meta_ptr)++;
11574 2 break;
11575 2 case MYSQL_TYPE_DATETIME2:
11576
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (**meta_ptr != 0)
11577 1 snprintf(typestr, typestr_length, "DATETIME(%d)", **meta_ptr);
11578 else
11579 1 snprintf(typestr, typestr_length, "DATETIME");
11580 2 (*meta_ptr)++;
11581 2 break;
11582 2 case MYSQL_TYPE_TIME2:
11583
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (**meta_ptr != 0)
11584 1 snprintf(typestr, typestr_length, "TIME(%d)", **meta_ptr);
11585 else
11586 1 snprintf(typestr, typestr_length, "TIME");
11587 2 (*meta_ptr)++;
11588 2 break;
11589 1 case MYSQL_TYPE_NEWDATE:
11590 case MYSQL_TYPE_DATE:
11591 1 snprintf(typestr, typestr_length, "DATE");
11592 1 break;
11593 2 case MYSQL_TYPE_YEAR:
11594 2 snprintf(typestr, typestr_length, "YEAR");
11595 2 break;
11596 17 case MYSQL_TYPE_ENUM:
11597 17 snprintf(typestr, typestr_length, "ENUM");
11598 17 (*meta_ptr) += 2;
11599 17 break;
11600 17 case MYSQL_TYPE_SET:
11601 17 snprintf(typestr, typestr_length, "SET");
11602 17 (*meta_ptr) += 2;
11603 17 break;
11604 16 case MYSQL_TYPE_BLOB: {
11605
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 5 times.
16 bool is_text = (cs && cs->number != my_charset_bin.number);
11606 16 const char *names[5][2] = {{"INVALID_BLOB(%d)", "INVALID_TEXT(%d)"},
11607 {"TINYBLOB", "TINYTEXT"},
11608 {"BLOB", "TEXT"},
11609 {"MEDIUMBLOB", "MEDIUMTEXT"},
11610 {"LONGBLOB", "LONGTEXT"}};
11611 16 unsigned char size = **meta_ptr;
11612
11613
3/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 15 times.
16 if (size == 0 || size > 4)
11614 1 snprintf(typestr, typestr_length, names[0][is_text], size);
11615 else
11616 15 snprintf(typestr, typestr_length, "%s", names[**meta_ptr][is_text]);
11617
11618 16 (*meta_ptr)++;
11619 16 } break;
11620 10 case MYSQL_TYPE_VARCHAR:
11621 case MYSQL_TYPE_VAR_STRING:
11622
3/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 1 times.
10 if (cs && cs->number != my_charset_bin.number)
11623 9 snprintf(typestr, typestr_length, "VARCHAR(%d)",
11624 9 uint2korr(*meta_ptr) / cs->mbmaxlen);
11625 else
11626 1 snprintf(typestr, typestr_length, "VARBINARY(%d)",
11627 1 uint2korr(*meta_ptr));
11628
11629 10 (*meta_ptr) += 2;
11630 10 break;
11631 21 case MYSQL_TYPE_STRING: {
11632 21 uint byte0 = (*meta_ptr)[0];
11633 21 uint byte1 = (*meta_ptr)[1];
11634 21 uint len = (((byte0 & 0x30) ^ 0x30) << 4) | byte1;
11635
11636
4/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 1 times.
21 if (cs && cs->number != my_charset_bin.number)
11637 17 snprintf(typestr, typestr_length, "CHAR(%d)", len / cs->mbmaxlen);
11638 else
11639 4 snprintf(typestr, typestr_length, "BINARY(%d)", len);
11640
11641 21 (*meta_ptr) += 2;
11642 21 } break;
11643 1 case MYSQL_TYPE_JSON:
11644 1 snprintf(typestr, typestr_length, "JSON");
11645 1 (*meta_ptr)++;
11646 1 break;
11647 25 case MYSQL_TYPE_GEOMETRY: {
11648 25 const char *names[8] = {
11649 "GEOMETRY", "POINT", "LINESTRING", "POLYGON",
11650 "MULTIPOINT", "MULTILINESTRING", "MULTIPOLYGON", "GEOMCOLLECTION"};
11651
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3 times.
25 if (geometry_type < 8)
11652 22 snprintf(typestr, typestr_length, "%s", names[geometry_type]);
11653 else
11654 3 snprintf(typestr, typestr_length, "INVALID_GEOMETRY_TYPE(%u)",
11655 geometry_type);
11656 25 (*meta_ptr)++;
11657 25 } break;
11658 1 case MYSQL_TYPE_INVALID:
11659 default:
11660 1 *typestr = 0;
11661 1 break;
11662 }
11663 177 }
11664
11665 /**
11666 Interface for iterator over charset columns.
11667 */
11668 class Table_map_log_event::Charset_iterator {
11669 public:
11670 typedef Table_map_event::Optional_metadata_fields::Default_charset
11671 Default_charset;
11672 virtual const CHARSET_INFO *next() = 0;
11673 148 virtual ~Charset_iterator() = default;
11674
11675 /**
11676 Factory method to create an instance of the appropriate subclass.
11677 */
11678 static std::unique_ptr<Charset_iterator> create_charset_iterator(
11679 const Default_charset &default_charset,
11680 const std::vector<uint> &column_charset);
11681 };
11682
11683 /**
11684 Implementation of charset iterator for the DEFAULT_CHARSET type.
11685 */
11686 class Table_map_log_event::Default_charset_iterator : public Charset_iterator {
11687 public:
11688 20 Default_charset_iterator(const Default_charset &default_charset)
11689 40 : m_iterator(default_charset.charset_pairs.begin()),
11690 20 m_end(default_charset.charset_pairs.end()),
11691 20 m_column_index(0),
11692 20 m_default_charset_info(
11693
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
40 get_charset(default_charset.default_charset, 0)) {}
11694
11695 44 const CHARSET_INFO *next() override {
11696 const CHARSET_INFO *ret;
11697
6/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 42 times.
44 if (m_iterator != m_end && m_iterator->first == m_column_index) {
11698 2 ret = get_charset(m_iterator->second, 0);
11699 2 m_iterator++;
11700 } else
11701 42 ret = m_default_charset_info;
11702 44 m_column_index++;
11703 44 return ret;
11704 }
11705
11706 private:
11707 std::vector<Optional_metadata_fields::uint_pair>::const_iterator m_iterator,
11708 m_end;
11709 uint m_column_index;
11710 const CHARSET_INFO *m_default_charset_info;
11711 };
11712
11713 /**
11714 Implementation of charset iterator for the COLUMNT_CHARSET type.
11715 */
11716 class Table_map_log_event::Column_charset_iterator : public Charset_iterator {
11717 public:
11718 54 Column_charset_iterator(const std::vector<uint> &column_charset)
11719 54 : m_iterator(column_charset.begin()), m_end(column_charset.end()) {}
11720
11721 37 const CHARSET_INFO *next() override {
11722 37 const CHARSET_INFO *ret = nullptr;
11723
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 22 times.
37 if (m_iterator != m_end) {
11724 15 ret = get_charset(*m_iterator, 0);
11725 15 m_iterator++;
11726 }
11727 37 return ret;
11728 }
11729
11730 private:
11731 std::vector<uint>::const_iterator m_iterator;
11732 std::vector<uint>::const_iterator m_end;
11733 };
11734
11735 std::unique_ptr<Table_map_log_event::Charset_iterator>
11736 74 Table_map_log_event::Charset_iterator::create_charset_iterator(
11737 const Default_charset &default_charset,
11738 const std::vector<uint> &column_charset) {
11739
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 54 times.
74 if (!default_charset.empty())
11740 return std::unique_ptr<Charset_iterator>(
11741
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 new Default_charset_iterator(default_charset));
11742 else
11743 return std::unique_ptr<Charset_iterator>(
11744 54 new Column_charset_iterator(column_charset));
11745 }
11746
11747 37 void Table_map_log_event::print_columns(
11748 IO_CACHE *file, const Optional_metadata_fields &fields) const {
11749 37 unsigned char *field_metadata_ptr = m_field_metadata;
11750 37 std::vector<bool>::const_iterator signedness_it = fields.m_signedness.begin();
11751
11752 std::unique_ptr<Charset_iterator> charset_it =
11753 37 Charset_iterator::create_charset_iterator(fields.m_default_charset,
11754
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 fields.m_column_charset);
11755 std::unique_ptr<Charset_iterator> enum_and_set_charset_it =
11756 Charset_iterator::create_charset_iterator(
11757 37 fields.m_enum_and_set_default_charset,
11758
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 fields.m_enum_and_set_column_charset);
11759 std::vector<std::string>::const_iterator col_names_it =
11760 37 fields.m_column_name.begin();
11761 std::vector<Optional_metadata_fields::str_vector>::const_iterator
11762 37 set_str_values_it = fields.m_set_str_value.begin();
11763 std::vector<Optional_metadata_fields::str_vector>::const_iterator
11764 37 enum_str_values_it = fields.m_enum_str_value.begin();
11765 std::vector<unsigned int>::const_iterator geometry_type_it =
11766 37 fields.m_geometry_type.begin();
11767 37 uint geometry_type = 0;
11768 std::vector<bool>::const_iterator column_visibility_it =
11769 37 fields.m_column_visibility.begin();
11770
11771
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 my_b_printf(file, "# Columns(");
11772
11773
2/2
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 37 times.
214 for (unsigned long i = 0; i < m_colcnt; i++) {
11774 177 uint real_type = m_coltype[i];
11775
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 122 times.
177 if (real_type == MYSQL_TYPE_STRING &&
11776
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 17 times.
55 (*field_metadata_ptr == MYSQL_TYPE_ENUM ||
11777
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 21 times.
38 *field_metadata_ptr == MYSQL_TYPE_SET))
11778 34 real_type = *field_metadata_ptr;
11779
11780 // Get current column's collation id if it is a character, enum,
11781 // or set column
11782 177 const CHARSET_INFO *cs = nullptr;
11783
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 130 times.
177 if (is_character_type(real_type))
11784
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 cs = charset_it->next();
11785
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 96 times.
130 else if (is_enum_or_set_type(real_type))
11786
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 cs = enum_and_set_charset_it->next();
11787
11788 // Print column name
11789
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 93 times.
177 if (col_names_it != fields.m_column_name.end()) {
11790
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 pretty_print_identifier(file, col_names_it->c_str(),
11791 col_names_it->size());
11792
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 my_b_printf(file, " ");
11793 84 col_names_it++;
11794 }
11795
11796 // update geometry_type for geometry columns
11797
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 152 times.
177 if (real_type == MYSQL_TYPE_GEOMETRY) {
11798 25 geometry_type = (geometry_type_it != fields.m_geometry_type.end())
11799
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1 times.
25 ? *geometry_type_it++
11800 : 0;
11801 }
11802
11803 // print column type
11804 177 const uint TYPE_NAME_LEN = 100;
11805 char type_name[TYPE_NAME_LEN];
11806 177 get_type_name(real_type, &field_metadata_ptr, cs, type_name, TYPE_NAME_LEN,
11807 geometry_type);
11808
11809
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 176 times.
177 if (type_name[0] == '\0') {
11810
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_b_printf(file, "INVALID_TYPE(%d)", real_type);
11811 1 continue;
11812 }
11813
1/2
✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
176 my_b_printf(file, "%s", type_name);
11814
11815 // Print UNSIGNED for numeric column
11816 176 enum_field_types field_type_code = static_cast<enum_field_types>(real_type);
11817
4/4
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 116 times.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 2 times.
236 if (has_signedess_information_type(field_type_code) &&
11818
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 118 times.
236 signedness_it != fields.m_signedness.end()) {
11819
6/6
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 38 times.
58 if (*signedness_it == true &&
11820 // the UNSIGNED modifier is encoded for YEAR but not used
11821 field_type_code != MYSQL_TYPE_YEAR)
11822
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 my_b_printf(file, " UNSIGNED");
11823 58 signedness_it++;
11824 }
11825
11826 // if the column is not marked as 'null', print 'not null'
11827
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 149 times.
176 if (!(m_null_bits[(i / 8)] & (1 << (i % 8))))
11828
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 my_b_printf(file, " NOT NULL");
11829
11830 // Print string values of SET and ENUM column
11831 176 const Optional_metadata_fields::str_vector *str_values = nullptr;
11832
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 159 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 9 times.
193 if (real_type == MYSQL_TYPE_ENUM &&
11833
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 168 times.
193 enum_str_values_it != fields.m_enum_str_value.end()) {
11834 8 str_values = &(*enum_str_values_it);
11835 8 enum_str_values_it++;
11836
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 151 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 9 times.
185 } else if (real_type == MYSQL_TYPE_SET &&
11837
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 160 times.
185 set_str_values_it != fields.m_set_str_value.end()) {
11838 8 str_values = &(*set_str_values_it);
11839 8 set_str_values_it++;
11840 }
11841
11842
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 160 times.
176 if (str_values != nullptr) {
11843 16 const char *separator = "(";
11844 16 for (Optional_metadata_fields::str_vector::const_iterator it =
11845 16 str_values->begin();
11846
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 16 times.
64 it != str_values->end(); it++) {
11847
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 my_b_printf(file, "%s", separator);
11848
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 pretty_print_str(file, it->c_str(), it->size());
11849 48 separator = ", ";
11850 }
11851
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 my_b_printf(file, ")");
11852 }
11853
11854 // Print column character set, except in text columns with binary collation
11855
6/6
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 117 times.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 52 times.
✓ Branch 5 taken 124 times.
278 if (cs != nullptr &&
11856
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 7 times.
102 (is_enum_or_set_type(real_type) || cs->number != my_charset_bin.number))
11857
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 my_b_printf(file, " CHARSET %s COLLATE %s", cs->csname, cs->m_coll_name);
11858
11859 // If column is invisible then print 'INVISIBLE'.
11860
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 89 times.
176 if (column_visibility_it != fields.m_column_visibility.end()) {
11861
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 73 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
87 if (!(*column_visibility_it)) my_b_printf(file, " INVISIBLE");
11862 87 column_visibility_it++;
11863 }
11864
11865
3/4
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 140 times.
✗ Branch 3 not taken.
176 if (i != m_colcnt - 1) my_b_printf(file, ",\n# ");
11866 }
11867
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 my_b_printf(file, ")");
11868
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 my_b_printf(file, "\n");
11869 37 }
11870
11871 37 void Table_map_log_event::print_primary_key(
11872 IO_CACHE *file, const Optional_metadata_fields &fields) const {
11873
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 32 times.
37 if (!fields.m_primary_key.empty()) {
11874
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_b_printf(file, "# Primary Key(");
11875
11876 std::vector<Optional_metadata_fields::uint_pair>::const_iterator it =
11877 5 fields.m_primary_key.begin();
11878
11879
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (; it != fields.m_primary_key.end(); it++) {
11880
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
11 if (it != fields.m_primary_key.begin()) my_b_printf(file, ", ");
11881
11882 // Print column name or column index
11883
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
11 if (it->first >= fields.m_column_name.size())
11884
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_b_printf(file, "%u", it->first);
11885 else
11886
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 my_b_printf(file, "%s", fields.m_column_name[it->first].c_str());
11887
11888 // Print prefix length
11889
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
11 if (it->second != 0) my_b_printf(file, "(%u)", it->second);
11890 }
11891
11892
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_b_printf(file, ")\n");
11893 }
11894 37 }
11895 #endif
11896
11897 /**************************************************************************
11898 Write_rows_log_event member functions
11899 **************************************************************************/
11900
11901 /*
11902 Constructor used to build an event for writing to the binary log.
11903 */
11904 #if defined(MYSQL_SERVER)
11905 50985156 Write_rows_log_event::Write_rows_log_event(
11906 THD *thd_arg, TABLE *tbl_arg, const Table_id &tid_arg,
11907 50985156 bool is_transactional, const unsigned char *extra_row_ndb_info)
11908 : binary_log::Rows_event(log_bin_use_v1_row_events
11909 ? binary_log::WRITE_ROWS_EVENT_V1
11910 : binary_log::WRITE_ROWS_EVENT),
11911 50985220 Rows_log_event(thd_arg, tbl_arg, tid_arg, tbl_arg->write_set,
11912 is_transactional,
11913 log_bin_use_v1_row_events ? binary_log::WRITE_ROWS_EVENT_V1
11914 : binary_log::WRITE_ROWS_EVENT,
11915
4/9
✗ Branch 0 not taken.
✓ Branch 1 taken 25492578 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25492610 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 25492340 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 25492288 times.
✗ Branch 8 not taken.
50985156 extra_row_ndb_info) {
11916 50984576 common_header->type_code = m_type;
11917 }
11918
11919 90387070 bool Write_rows_log_event::binlog_row_logging_function(
11920 THD *thd_arg, TABLE *table, bool is_transactional,
11921 const uchar *before_record [[maybe_unused]], const uchar *after_record) {
11922 90387070 return thd_arg->binlog_write_row(table, is_transactional, after_record,
11923 90435172 nullptr);
11924 }
11925 #endif
11926
11927 /*
11928 Constructor used by slave to read the event from the binary log.
11929 */
11930 45690676 Write_rows_log_event::Write_rows_log_event(
11931 45690676 const char *buf, const Format_description_event *description_event)
11932 : binary_log::Rows_event(buf, description_event),
11933 Rows_log_event(buf, description_event),
11934
2/4
✓ Branch 0 taken 22845338 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22845338 times.
✗ Branch 3 not taken.
45690676 binary_log::Write_rows_event(buf, description_event) {
11935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22845338 times.
45690676 assert(header()->type_code == m_type);
11936 }
11937
11938 #if defined(MYSQL_SERVER)
11939 241956 int Write_rows_log_event::do_before_row_operations(
11940 const Slave_reporting_capability *const) {
11941 241956 int error = 0;
11942
11943 241956 m_table->file->rpl_before_write_rows();
11944
11945 /*
11946 Increment the global status insert count variable
11947 */
11948
2/2
✓ Branch 0 taken 234346 times.
✓ Branch 1 taken 7691 times.
241956 if (get_flags(STMT_END_F)) thd->status_var.com_stat[SQLCOM_INSERT]++;
11949
11950 /*
11951 Let storage engines treat this event as an INSERT command.
11952
11953 Set 'sql_command' as SQLCOM_INSERT after the tables are locked.
11954 When locking the tables, it should be SQLCOM_END.
11955 THD::decide_logging_format which is called from "lock tables"
11956 assumes that row_events will have 'sql_command' as SQLCOM_END.
11957 */
11958 242037 thd->lex->sql_command = SQLCOM_INSERT;
11959
11960
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 242028 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
242037 DBUG_EXECUTE_IF(
11961 "crash_on_transactional_ddl_insert",
11962 if (thd->m_transactional_ddl.inited()) { DBUG_SUICIDE(); });
11963
11964 /**
11965 todo: to introduce a property for the event (handler?) which forces
11966 applying the event in the replace (idempotent) fashion.
11967 */
11968
4/4
✓ Branch 0 taken 241953 times.
✓ Branch 1 taken 84 times.
✓ Branch 2 taken 82 times.
✓ Branch 3 taken 241965 times.
484000 if ((rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT) ||
11969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241965 times.
241953 (m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER)) {
11970 /*
11971 We are using REPLACE semantics and not INSERT IGNORE semantics
11972 when writing rows, that is: new rows replace old rows. We need to
11973 inform the storage engine that it should use this behaviour.
11974 */
11975
11976 /* Tell the storage engine that we are using REPLACE semantics. */
11977 82 thd->lex->duplicates = DUP_REPLACE;
11978
11979 /*
11980 Pretend we're executing a REPLACE command: this is needed for
11981 InnoDB and NDB Cluster since they are not (properly) checking the
11982 lex->duplicates flag.
11983 */
11984 82 thd->lex->sql_command = SQLCOM_REPLACE;
11985 /*
11986 Do not raise the error flag in case of hitting to an unique attribute
11987 */
11988 82 m_table->file->ha_extra(HA_EXTRA_IGNORE_DUP_KEY);
11989 /*
11990 NDB specific: update from ndb master wrapped as Write_rows
11991 so that the event should be applied to replace slave's row
11992 */
11993 82 m_table->file->ha_extra(HA_EXTRA_WRITE_CAN_REPLACE);
11994 /*
11995 NDB specific: if update from ndb master wrapped as Write_rows
11996 does not find the row it's assumed idempotent binlog applying
11997 is taking place; don't raise the error.
11998 */
11999 82 m_table->file->ha_extra(HA_EXTRA_IGNORE_NO_KEY);
12000 /*
12001 TODO: the cluster team (Tomas?) says that it's better if the engine knows
12002 how many rows are going to be inserted, then it can allocate needed memory
12003 from the start.
12004 */
12005 }
12006
12007 /* Honor next number column if present */
12008 242047 m_table->next_number_field = m_table->found_next_number_field;
12009 /*
12010 * Fixed Bug#45999, In RBR, Store engine of Slave auto-generates new
12011 * sequence numbers for auto_increment fields if the values of them are 0.
12012 * If generateing a sequence number is decided by the values of
12013 * table->autoinc_field_has_explicit_non_null_value and SQL_MODE(if
12014 * includes MODE_NO_AUTO_VALUE_ON_ZERO) in update_auto_increment function.
12015 * SQL_MODE of slave sql thread is always consistency with master's.
12016 * In RBR, auto_increment fields never are NULL, except if the auto_inc
12017 * column exists only on the slave side (i.e., in an extra column
12018 * on the slave's table).
12019 */
12020
2/2
✓ Branch 0 taken 241801 times.
✓ Branch 1 taken 173 times.
242047 if (!is_auto_inc_in_extra_columns())
12021 241801 m_table->autoinc_field_has_explicit_non_null_value = true;
12022 else {
12023 /*
12024 Here we have checked that there is an extra field
12025 on this server's table that has an auto_inc column.
12026
12027 Mark that the auto_increment field is null and mark
12028 the read and write set bits.
12029
12030 (There can only be one AUTO_INC column, it is always
12031 indexed and it cannot have a DEFAULT value).
12032 */
12033 173 m_table->autoinc_field_has_explicit_non_null_value = false;
12034 173 m_table->mark_auto_increment_column();
12035 }
12036
12037 /**
12038 Sets it to ROW_LOOKUP_NOT_NEEDED.
12039 */
12040 241988 decide_row_lookup_algorithm_and_key();
12041
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 241998 times.
242004 assert(m_rows_lookup_algorithm == ROW_LOOKUP_NOT_NEEDED);
12042
12043 241998 return error;
12044 }
12045
12046 242037 int Write_rows_log_event::do_after_row_operations(
12047 const Slave_reporting_capability *const, int error) {
12048 242037 int local_error = 0;
12049
12050 /**
12051 Clear the write_set bit for auto_inc field that only
12052 existed on the destination table as an extra column.
12053 */
12054
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 241862 times.
242037 if (is_auto_inc_in_extra_columns()) {
12055 187 bitmap_clear_bit(m_table->write_set,
12056 187 m_table->next_number_field->field_index());
12057 187 bitmap_clear_bit(m_table->read_set,
12058 187 m_table->next_number_field->field_index());
12059
12060
1/2
✓ Branch 0 taken 187 times.
✗ Branch 1 not taken.
187 if (get_flags(STMT_END_F)) m_table->file->ha_release_auto_increment();
12061 }
12062 242049 m_table->next_number_field = nullptr;
12063 242049 m_table->autoinc_field_has_explicit_non_null_value = false;
12064
12065 /**
12066 Row based replication for Ndb requires resetting flags after each event.
12067 This is symmetric with do_before_row_operations.
12068 */
12069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 242057 times.
242049 if (m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER) {
12070 m_table->file->ha_extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
12071 m_table->file->ha_extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
12072 }
12073
12074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 242060 times.
242057 if ((local_error = m_table->file->ha_end_bulk_insert())) {
12075 m_table->file->print_error(local_error, MYF(0));
12076 }
12077
12078 242060 m_rows_lookup_algorithm = ROW_LOOKUP_UNDEFINED;
12079 242060 m_table->file->rpl_after_write_rows();
12080
12081
2/2
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 241871 times.
242035 return error ? error : local_error;
12082 }
12083
12084 /*
12085 Check if there are more UNIQUE keys after the given key.
12086 */
12087 41 static int last_uniq_key(TABLE *table, uint keyno) {
12088
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 35 times.
41 while (++keyno < table->s->keys)
12089
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (table->key_info[keyno].flags & HA_NOSAME) return 0;
12090 35 return 1;
12091 }
12092
12093 /**
12094 Write the current row into event's table.
12095
12096 The row is located in the row buffer, pointed by @c m_curr_row member.
12097 Number of columns of the row is stored in @c m_width member (it can be
12098 different from the number of columns in the table to which we insert).
12099 Bitmap @c m_cols indicates which columns are present in the row. It is assumed
12100 that event's table is already open and pointed by @c m_table.
12101
12102 If the same record already exists in the table it can be either overwritten
12103 or an error is reported depending on the value of @c overwrite flag
12104 (error reporting not yet implemented). Note that the matching record can be
12105 different from the row we insert if we use primary keys to identify records in
12106 the table.
12107
12108 The row to be inserted can contain values only for selected columns. The
12109 missing columns are filled with default values using @c prepare_record()
12110 function. If a matching record is found in the table and @c overwritte is
12111 true, the missing columns are taken from it.
12112
12113 @param rli Relay log info (needed for row unpacking).
12114 @param overwrite
12115 Shall we overwrite if the row already exists or signal
12116 error (currently ignored).
12117
12118 @returns Error code on failure, 0 on success.
12119
12120 This method, if successful, sets @c m_curr_row_end pointer to point at the
12121 next row in the rows buffer. This is done when unpacking the row to be
12122 inserted.
12123
12124 @note If a matching record is found, it is either updated using
12125 @c ha_update_row() or first deleted and then new record written.
12126 */
12127
12128 502851 int Write_rows_log_event::write_row(const Relay_log_info *const rli,
12129 const bool overwrite) {
12130
1/2
✓ Branch 0 taken 502941 times.
✗ Branch 1 not taken.
502851 DBUG_TRACE;
12131
3/4
✓ Branch 0 taken 502941 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 502936 times.
✓ Branch 3 taken 5 times.
502941 assert(m_table != nullptr && thd != nullptr);
12132
12133 502936 TABLE *table = m_table; // pointer to event's table
12134 int error;
12135 502936 int keynum = 0;
12136 502936 char *key = nullptr;
12137
12138 502936 prepare_record(table, &this->m_local_cols,
12139
1/2
✓ Branch 0 taken 502942 times.
✗ Branch 1 not taken.
502936 table->file->ht->db_type != DB_TYPE_NDBCLUSTER);
12140
12141 /* unpack row into table->record[0] */
12142
2/4
✓ Branch 0 taken 502842 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 502842 times.
502942 if ((error = unpack_current_row(rli, &m_cols, true /*is AI*/))) return error;
12143
12144 /*
12145 When m_curr_row == m_curr_row_end, it means a row that contains nothing,
12146 so all the pointers shall be pointing to the same address, or else
12147 we have corrupt data and shall throw the error.
12148 */
12149
3/8
✓ Branch 0 taken 502916 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 502883 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 502883 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
502842 DBUG_PRINT("debug", ("m_rows_buf= %p, m_rows_cur= %p, m_rows_end= %p",
12150 m_rows_buf, m_rows_cur, m_rows_end));
12151
3/8
✓ Branch 0 taken 502924 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 502926 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 502926 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
502883 DBUG_PRINT("debug", ("m_curr_row= %p, m_curr_row_end= %p", m_curr_row,
12152 m_curr_row_end));
12153
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 502920 times.
502926 if (m_curr_row == m_curr_row_end &&
12154
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 !((m_rows_buf == m_rows_cur) && (m_rows_cur == m_rows_end))) {
12155 my_error(ER_SLAVE_CORRUPT_EVENT, MYF(0));
12156 return ER_SLAVE_CORRUPT_EVENT;
12157 }
12158
12159 // Invoke check constraints on the unpacked row.
12160
2/4
✓ Branch 0 taken 502832 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 502832 times.
502926 if (invoke_table_check_constraints(thd, table))
12161 return ER_CHECK_CONSTRAINT_VIOLATED;
12162
12163
2/2
✓ Branch 0 taken 241973 times.
✓ Branch 1 taken 260859 times.
502832 if (m_curr_row == m_rows_buf) {
12164 /* this is the first row to be inserted, we estimate the rows with
12165 the size of the first row and use that value to initialize
12166 storage engine for bulk insertion */
12167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241973 times.
241973 assert(!(m_curr_row > m_curr_row_end));
12168 241973 ulong estimated_rows = 0;
12169
1/2
✓ Branch 0 taken 242013 times.
✗ Branch 1 not taken.
241973 if (m_curr_row < m_curr_row_end)
12170 242013 estimated_rows =
12171 242013 (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row);
12172 else if (m_curr_row == m_curr_row_end)
12173 6 estimated_rows = 1;
12174
12175
1/2
✓ Branch 0 taken 242052 times.
✗ Branch 1 not taken.
241973 m_table->file->ha_start_bulk_insert(estimated_rows);
12176 }
12177
12178 /*
12179 Explicitly set the auto_inc to null to make sure that
12180 it gets an auto_generated value.
12181 */
12182
4/6
✓ Branch 0 taken 502944 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 187 times.
✓ Branch 3 taken 502757 times.
✓ Branch 4 taken 187 times.
✗ Branch 5 not taken.
502911 if (is_auto_inc_in_extra_columns()) m_table->next_number_field->set_null();
12183
12184 #ifndef NDEBUG
12185
1/2
✓ Branch 0 taken 502937 times.
✗ Branch 1 not taken.
502944 DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
12186
7/12
✓ Branch 0 taken 1039855 times.
✓ Branch 1 taken 1021 times.
✓ Branch 2 taken 1040899 times.
✓ Branch 3 taken 502929 times.
✓ Branch 4 taken 502927 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 502937 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 502937 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1543813 DBUG_PRINT_BITSET("debug", "write_set = %s", table->write_set);
12187
7/12
✓ Branch 0 taken 1040896 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1040905 times.
✓ Branch 3 taken 502933 times.
✓ Branch 4 taken 502939 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 502944 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 502944 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1543837 DBUG_PRINT_BITSET("debug", "read_set = %s", table->read_set);
12188 #endif
12189
12190 /*
12191 Try to write record. If a corresponding record already exists in the table,
12192 we try to change it using ha_update_row() if possible. Otherwise we delete
12193 it and repeat the whole process again.
12194
12195 TODO: Add safety measures against infinite looping.
12196 */
12197
12198
1/2
✓ Branch 0 taken 502872 times.
✗ Branch 1 not taken.
502944 m_table->mark_columns_per_binlog_row_image(thd);
12199
12200
3/4
✓ Branch 0 taken 502934 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 213 times.
✓ Branch 3 taken 502721 times.
502878 while ((error = table->file->ha_write_row(table->record[0]))) {
12201
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 97 times.
201 if (error == HA_ERR_LOCK_DEADLOCK || error == HA_ERR_LOCK_WAIT_TIMEOUT ||
12202
9/10
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 104 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 100 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 59 times.
✓ Branch 7 taken 41 times.
✓ Branch 8 taken 172 times.
✓ Branch 9 taken 41 times.
414 (keynum = table->file->get_dup_key(error)) < 0 || !overwrite) {
12203
3/8
✓ Branch 0 taken 173 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 172 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 172 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
172 DBUG_PRINT("info", ("get_dup_key returns %d)", keynum));
12204 /*
12205 Deadlock, waiting for lock or just an error from the handler
12206 such as HA_ERR_FOUND_DUPP_KEY when overwrite is false.
12207 Retrieval of the duplicate key number may fail
12208 - either because the error was not "duplicate key" error
12209 - or because the information which key is not available
12210 */
12211
1/2
✓ Branch 0 taken 173 times.
✗ Branch 1 not taken.
172 table->file->print_error(error, MYF(0));
12212 173 goto error;
12213 }
12214 /*
12215 key index value is either valid in the range [0-MAX_KEY) or
12216 has value MAX_KEY as a marker for the case when no information
12217 about key can be found. In the last case we have to require
12218 that storage engine has the flag HA_DUPLICATE_POS turned on.
12219 If this invariant is false then assert will crash
12220 the server built in debug mode. For the server that was built
12221 without DEBUG we have additional check for the value of key index
12222 in the code below in order to report about error in any case.
12223 */
12224
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
41 assert(keynum != MAX_KEY ||
12225 (keynum == MAX_KEY &&
12226 (table->file->ha_table_flags() & HA_DUPLICATE_POS)));
12227 /*
12228 We need to retrieve the old row into record[1] to be able to
12229 either update or delete the offending record. We either:
12230
12231 - use ha_rnd_pos() with a row-id (available as dupp_row) to the
12232 offending row, if that is possible (MyISAM and Blackhole), or else
12233
12234 - use ha_index_read_idx_map() with the key that is duplicated, to
12235 retrieve the offending row.
12236 */
12237
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 34 times.
41 if (table->file->ha_table_flags() & HA_DUPLICATE_POS) {
12238
3/8
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7 DBUG_PRINT("info", ("Locating offending record using ha_rnd_pos()"));
12239
12240
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
7 if (table->file->inited && (error = table->file->ha_index_end())) {
12241 table->file->print_error(error, MYF(0));
12242 goto error;
12243 }
12244
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if ((error = table->file->ha_rnd_init(false))) {
12245 table->file->print_error(error, MYF(0));
12246 goto error;
12247 }
12248
12249
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 error = table->file->ha_rnd_pos(table->record[1], table->file->dup_ref);
12250
12251
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 table->file->ha_rnd_end();
12252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (error) {
12253 DBUG_PRINT("info", ("ha_rnd_pos() returns error %d", error));
12254 if (error == HA_ERR_RECORD_DELETED) error = HA_ERR_KEY_NOT_FOUND;
12255 table->file->print_error(error, MYF(0));
12256 goto error;
12257 }
12258 } else {
12259
3/8
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 34 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
34 DBUG_PRINT("info", ("Locating offending record using index_read_idx()"));
12260
12261
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 if (key == nullptr) {
12262 34 key = static_cast<char *>(my_alloca(table->s->max_unique_length));
12263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (key == nullptr) {
12264 DBUG_PRINT("info", ("Can't allocate key buffer"));
12265 error = ENOMEM;
12266 goto error;
12267 }
12268 }
12269
12270
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 if ((uint)keynum < MAX_KEY) {
12271
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 key_copy((uchar *)key, table->record[0], table->key_info + keynum, 0);
12272
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 error = table->file->ha_index_read_idx_map(
12273 table->record[1], keynum, (const uchar *)key, HA_WHOLE_KEY,
12274 HA_READ_KEY_EXACT);
12275 } else
12276 /*
12277 For the server built in non-debug mode returns error if
12278 handler::get_dup_key() returned MAX_KEY as the value of key index.
12279 */
12280 error = HA_ERR_FOUND_DUPP_KEY;
12281
12282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (error) {
12283 DBUG_PRINT("info",
12284 ("ha_index_read_idx_map() returns %s", HA_ERR(error)));
12285 if (error == HA_ERR_RECORD_DELETED) error = HA_ERR_KEY_NOT_FOUND;
12286 table->file->print_error(error, MYF(0));
12287 goto error;
12288 }
12289 }
12290
12291 /*
12292 Now, record[1] should contain the offending row. That
12293 will enable us to update it or, alternatively, delete it (so
12294 that we can insert the new row afterwards).
12295 */
12296
12297 /*
12298 If row is incomplete we will use the record found to fill
12299 missing columns.
12300 */
12301
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 26 times.
41 if (!get_flags(COMPLETE_ROWS_F)) {
12302 15 restore_record(table, record[1]);
12303
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 error = unpack_current_row(rli, &m_cols, true /*is AI*/);
12304 }
12305
12306 #ifndef NDEBUG
12307
3/8
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 41 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
41 DBUG_PRINT("debug", ("preparing for update: before and after image"));
12308
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 DBUG_DUMP("record[1] (before)", table->record[1], table->s->reclength);
12309
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 DBUG_DUMP("record[0] (after)", table->record[0], table->s->reclength);
12310 #endif
12311
12312 /*
12313 REPLACE is defined as either INSERT or DELETE + INSERT. If
12314 possible, we can replace it with an UPDATE, but that will not
12315 work on InnoDB if FOREIGN KEY checks are necessary.
12316
12317 I (Matz) am not sure of the reason for the last_uniq_key()
12318 check as, but I'm guessing that it's something along the
12319 following lines.
12320
12321 Suppose that we got the duplicate key to be a key that is not
12322 the last unique key for the table and we perform an update:
12323 then there might be another key for which the unique check will
12324 fail, so we're better off just deleting the row and inserting
12325 the correct row.
12326 */
12327
4/4
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 6 times.
76 if (last_uniq_key(table, keynum) &&
12328
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 !table->s->is_referenced_by_foreign_key()) {
12329
3/8
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 35 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
35 DBUG_PRINT("info", ("Updating row using ha_update_row()"));
12330
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 error = table->file->ha_update_row(table->record[1], table->record[0]);
12331
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
35 switch (error) {
12332 2 case HA_ERR_RECORD_IS_THE_SAME:
12333
3/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2 DBUG_PRINT("info", ("ignoring HA_ERR_RECORD_IS_THE_SAME error from"
12334 " ha_update_row()"));
12335 2 error = 0;
12336
12337 35 case 0:
12338 35 break;
12339
12340 default:
12341 DBUG_PRINT("info", ("ha_update_row() returns error %d", error));
12342 table->file->print_error(error, MYF(0));
12343 }
12344
12345 35 goto error;
12346 } else {
12347
3/8
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
6 DBUG_PRINT("info",
12348 ("Deleting offending row and trying to write new one again"));
12349
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if ((error = table->file->ha_delete_row(table->record[1]))) {
12350 DBUG_PRINT("info", ("ha_delete_row() returns error %d", error));
12351 table->file->print_error(error, MYF(0));
12352 goto error;
12353 }
12354 /* Will retry ha_write_row() with the offending row removed. */
12355 }
12356 }
12357
12358 502721 error:
12359 502929 m_table->default_column_bitmaps();
12360 502938 return error;
12361 502938 }
12362
12363 502847 int Write_rows_log_event::do_exec_row(const Relay_log_info *const rli) {
12364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 502847 times.
502847 assert(m_table != nullptr);
12365 502847 int error = write_row(rli, rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT);
12366
12367
4/6
✓ Branch 0 taken 175 times.
✓ Branch 1 taken 502773 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 173 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 502946 times.
502948 if (error && !thd->is_error()) {
12368 assert(0);
12369 my_error(ER_UNKNOWN_ERROR, MYF(0));
12370 }
12371
12372 502946 return error;
12373 }
12374
12375 #endif /* defined(MYSQL_SERVER) */
12376
12377 #ifndef MYSQL_SERVER
12378 22670 void Write_rows_log_event::print(FILE *file,
12379 PRINT_EVENT_INFO *print_event_info) const {
12380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22670 times.
22670 DBUG_EXECUTE_IF("simulate_cache_read_error",
12381 { DBUG_SET("+d,simulate_my_b_fill_error"); });
12382 22670 Rows_log_event::print_helper(file, print_event_info);
12383 22670 }
12384 #endif
12385
12386 /**************************************************************************
12387 Delete_rows_log_event member functions
12388 **************************************************************************/
12389
12390 /*
12391 Constructor used to build an event for writing to the binary log.
12392 */
12393
12394 #ifdef MYSQL_SERVER
12395 242622 Delete_rows_log_event::Delete_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
12396 const Table_id &tid,
12397 bool is_transactional,
12398 242622 const uchar *extra_row_ndb_info)
12399 : binary_log::Rows_event(log_bin_use_v1_row_events
12400 ? binary_log::DELETE_ROWS_EVENT_V1
12401 : binary_log::DELETE_ROWS_EVENT),
12402 242622 Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional,
12403 log_bin_use_v1_row_events
12404 ? binary_log::DELETE_ROWS_EVENT_V1
12405 : binary_log::DELETE_ROWS_EVENT,
12406 extra_row_ndb_info),
12407
4/9
✗ Branch 0 not taken.
✓ Branch 1 taken 121311 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 121311 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 121311 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 121311 times.
✗ Branch 8 not taken.
242622 binary_log::Delete_rows_event() {
12408 242622 common_header->type_code = m_type;
12409 }
12410
12411 1984449 bool Delete_rows_log_event::binlog_row_logging_function(
12412 THD *thd_arg, TABLE *table, bool is_transactional,
12413 const uchar *before_record, const uchar *after_record [[maybe_unused]]) {
12414 1984449 return thd_arg->binlog_delete_row(table, is_transactional, before_record,
12415 1984449 nullptr);
12416 }
12417
12418 #endif /* #if defined(MYSQL_SERVER) */
12419
12420 /*
12421 Constructor used by slave to read the event from the binary log.
12422 */
12423 103842 Delete_rows_log_event::Delete_rows_log_event(
12424 103842 const char *buf, const Format_description_event *description_event)
12425 : binary_log::Rows_event(buf, description_event),
12426 Rows_log_event(buf, description_event),
12427
2/4
✓ Branch 0 taken 51921 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 51921 times.
✗ Branch 3 not taken.
103842 binary_log::Delete_rows_event(buf, description_event) {
12428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51921 times.
103842 assert(header()->type_code == m_type);
12429 }
12430
12431 #if defined(MYSQL_SERVER)
12432
12433 22688 int Delete_rows_log_event::do_before_row_operations(
12434 const Slave_reporting_capability *const) {
12435 22688 int error = 0;
12436
1/2
✓ Branch 0 taken 22688 times.
✗ Branch 1 not taken.
22688 DBUG_TRACE;
12437
1/2
✓ Branch 0 taken 22688 times.
✗ Branch 1 not taken.
22688 m_table->file->rpl_before_delete_rows();
12438 /*
12439 Increment the global status delete count variable
12440 */
12441
2/2
✓ Branch 0 taken 21699 times.
✓ Branch 1 taken 989 times.
22688 if (get_flags(STMT_END_F)) thd->status_var.com_stat[SQLCOM_DELETE]++;
12442
12443 /*
12444 Let storage engines treat this event as a DELETE command.
12445
12446 Set 'sql_command' as SQLCOM_UPDATE after the tables are locked.
12447 When locking the tables, it should be SQLCOM_END.
12448 THD::decide_logging_format which is called from "lock tables"
12449 assumes that row_events will have 'sql_command' as SQLCOM_END.
12450 */
12451 22688 thd->lex->sql_command = SQLCOM_DELETE;
12452
12453
1/2
✓ Branch 0 taken 22688 times.
✗ Branch 1 not taken.
22688 error = row_operations_scan_and_key_setup();
12454 22688 return error;
12455 22688 }
12456
12457 22688 int Delete_rows_log_event::do_after_row_operations(
12458 const Slave_reporting_capability *const, int error) {
12459
1/2
✓ Branch 0 taken 22688 times.
✗ Branch 1 not taken.
22688 DBUG_TRACE;
12460
1/2
✓ Branch 0 taken 22688 times.
✗ Branch 1 not taken.
22688 error = row_operations_scan_and_key_teardown(error);
12461
1/2
✓ Branch 0 taken 22688 times.
✗ Branch 1 not taken.
22688 m_table->file->rpl_after_delete_rows();
12462 22688 return error;
12463 22688 }
12464
12465 50629 int Delete_rows_log_event::do_exec_row(const Relay_log_info *const rli) {
12466 int error;
12467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50629 times.
50629 assert(m_table != nullptr);
12468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50629 times.
50629 if (m_rows_lookup_algorithm == ROW_LOOKUP_NOT_NEEDED) {
12469 error = unpack_current_row(rli, &m_cols, false, false);
12470 if (error) return error;
12471 }
12472 /* m_table->record[0] contains the BI */
12473 50629 m_table->mark_columns_per_binlog_row_image(thd);
12474 50629 error = m_table->file->ha_delete_row(m_table->record[0]);
12475 50629 m_table->default_column_bitmaps();
12476 50629 return error;
12477 }
12478
12479 #endif /* defined(MYSQL_SERVER) */
12480
12481 #ifndef MYSQL_SERVER
12482 2478 void Delete_rows_log_event::print(FILE *file,
12483 PRINT_EVENT_INFO *print_event_info) const {
12484 2478 Rows_log_event::print_helper(file, print_event_info);
12485 2478 }
12486 #endif
12487
12488 /**************************************************************************
12489 Update_rows_log_event member functions
12490 **************************************************************************/
12491
12492 #if defined(MYSQL_SERVER)
12493 1320228 binary_log::Log_event_type Update_rows_log_event::get_update_rows_event_type(
12494 const THD *thd_arg) {
12495
1/2
✓ Branch 0 taken 1320228 times.
✗ Branch 1 not taken.
1320228 DBUG_TRACE;
12496 1320228 binary_log::Log_event_type type =
12497 1320228 (thd_arg->variables.binlog_row_value_options != 0
12498
2/2
✓ Branch 0 taken 1311675 times.
✓ Branch 1 taken 8553 times.
2631903 ? binary_log::PARTIAL_UPDATE_ROWS_EVENT
12499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1311675 times.
1311675 : (log_bin_use_v1_row_events ? binary_log::UPDATE_ROWS_EVENT_V1
12500 : binary_log::UPDATE_ROWS_EVENT));
12501
3/10
✓ Branch 0 taken 1320228 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1320228 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1320228 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1320228 DBUG_PRINT("info", ("update_rows event_type: %s", get_type_str(type)));
12502 1320228 return type;
12503 1320228 }
12504
12505 /*
12506 Constructor used to build an event for writing to the binary log.
12507 */
12508 880152 Update_rows_log_event::Update_rows_log_event(
12509 THD *thd_arg, TABLE *tbl_arg, const Table_id &tid, bool is_transactional,
12510 880152 const unsigned char *extra_row_ndb_info)
12511 : binary_log::Rows_event(get_update_rows_event_type(thd_arg)),
12512 880152 Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional,
12513 get_update_rows_event_type(thd_arg), extra_row_ndb_info),
12514
4/8
✓ Branch 0 taken 440076 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 440076 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 440076 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 440076 times.
✗ Branch 7 not taken.
880152 binary_log::Update_rows_event(get_update_rows_event_type(thd_arg)) {
12515
1/2
✓ Branch 0 taken 440076 times.
✗ Branch 1 not taken.
880152 DBUG_TRACE;
12516
3/10
✓ Branch 0 taken 440076 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 440076 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 440076 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
880152 DBUG_PRINT("info", ("update_rows event_type: %s", get_type_str()));
12517 880152 common_header->type_code = m_type;
12518
1/2
✓ Branch 0 taken 440076 times.
✗ Branch 1 not taken.
880152 init(tbl_arg->write_set);
12519
2/6
✓ Branch 0 taken 440076 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 440076 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
880152 common_header->set_is_valid(Rows_log_event::is_valid() && m_cols_ai.bitmap);
12520 }
12521
12522 3018045 bool Update_rows_log_event::binlog_row_logging_function(
12523 THD *thd_arg, TABLE *table, bool is_transactional,
12524 const uchar *before_record, const uchar *after_record) {
12525 3018045 return thd_arg->binlog_update_row(table, is_transactional, before_record,
12526 3018045 after_record, nullptr);
12527 }
12528
12529 440076 void Update_rows_log_event::init(MY_BITMAP const *cols) {
12530 /* if bitmap_init fails, caught in is_valid() */
12531
1/2
✓ Branch 0 taken 440076 times.
✗ Branch 1 not taken.
440076 if (likely(!bitmap_init(
12532 &m_cols_ai,
12533 440076 m_width <= sizeof(m_bitbuf_ai) * 8 ? m_bitbuf_ai : nullptr,
12534
2/2
✓ Branch 0 taken 440063 times.
✓ Branch 1 taken 13 times.
440076 m_width))) {
12535 /* Cols can be zero if this is a dummy binrows event */
12536
1/2
✓ Branch 0 taken 440076 times.
✗ Branch 1 not taken.
440076 if (likely(cols != nullptr)) {
12537 // 'cols' may have additional hidden columns at the end.
12538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 440076 times.
440076 assert(cols->n_bits >= m_cols_ai.n_bits);
12539 440076 bitmap_n_copy(&m_cols_ai, cols);
12540 }
12541 }
12542 440076 }
12543 #endif /* defined(MYSQL_SERVER) */
12544
12545 2638116 Update_rows_log_event::~Update_rows_log_event() {
12546
1/2
✓ Branch 0 taken 659529 times.
✗ Branch 1 not taken.
1319058 if (m_cols_ai.bitmap) {
12547
2/2
✓ Branch 0 taken 659509 times.
✓ Branch 1 taken 20 times.
1319058 if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened
12548 1319018 m_cols_ai.bitmap = nullptr; // so no my_free in bitmap_free
12549 1319058 bitmap_free(&m_cols_ai); // To pair with bitmap_init().
12550 }
12551 }
12552
12553 /*
12554 Constructor used by slave to read the event from the binary log.
12555 */
12556 438916 Update_rows_log_event::Update_rows_log_event(
12557 438916 const char *buf, const Format_description_event *description_event)
12558 : binary_log::Rows_event(buf, description_event),
12559 Rows_log_event(buf, description_event),
12560
2/4
✓ Branch 0 taken 219458 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219458 times.
✗ Branch 3 not taken.
438916 binary_log::Update_rows_event(buf, description_event) {
12561
1/2
✓ Branch 0 taken 219458 times.
✗ Branch 1 not taken.
438916 DBUG_TRACE;
12562
3/4
✓ Branch 0 taken 211521 times.
✓ Branch 1 taken 7937 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 211521 times.
438916 if (!is_valid()) return;
12563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219458 times.
438916 assert(header()->type_code == m_type);
12564 438916 common_header->set_is_valid(m_cols_ai.bitmap);
12565 }
12566
12567 #if defined(MYSQL_SERVER)
12568
12569 31703 int Update_rows_log_event::do_before_row_operations(
12570 const Slave_reporting_capability *const) {
12571 31703 int error = 0;
12572
1/2
✓ Branch 0 taken 31704 times.
✗ Branch 1 not taken.
31703 DBUG_TRACE;
12573
1/2
✓ Branch 0 taken 31703 times.
✗ Branch 1 not taken.
31704 m_table->file->rpl_before_update_rows();
12574 /*
12575 Increment the global status update count variable
12576 */
12577
2/2
✓ Branch 0 taken 30775 times.
✓ Branch 1 taken 929 times.
31703 if (get_flags(STMT_END_F)) thd->status_var.com_stat[SQLCOM_UPDATE]++;
12578
12579 /*
12580 Let storage engines treat this event as an UPDATE command.
12581
12582 Set 'sql_command' as SQLCOM_UPDATE after the tables are locked.
12583 When locking the tables, it should be SQLCOM_END.
12584 THD::decide_logging_format which is called from "lock tables"
12585 assumes that row_events will have 'sql_command' as SQLCOM_END.
12586 */
12587 31704 thd->lex->sql_command = SQLCOM_UPDATE;
12588
12589
1/2
✓ Branch 0 taken 31704 times.
✗ Branch 1 not taken.
31704 error = row_operations_scan_and_key_setup();
12590 31704 return error;
12591 31704 }
12592
12593 31701 int Update_rows_log_event::do_after_row_operations(
12594 const Slave_reporting_capability *const, int error) {
12595
1/2
✓ Branch 0 taken 31701 times.
✗ Branch 1 not taken.
31701 DBUG_TRACE;
12596
1/2
✓ Branch 0 taken 31701 times.
✗ Branch 1 not taken.
31701 error = row_operations_scan_and_key_teardown(error);
12597
1/2
✓ Branch 0 taken 31701 times.
✗ Branch 1 not taken.
31701 m_table->file->rpl_after_update_rows();
12598 31701 return error;
12599 31701 }
12600
12601 219111 int Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) {
12602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219111 times.
219111 assert(m_table != nullptr);
12603 219111 int error = 0;
12604
12605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 219111 times.
219111 if (m_rows_lookup_algorithm == ROW_LOOKUP_NOT_NEEDED) {
12606 error = unpack_current_row(rli, &m_cols, false, false);
12607 if (error) return error;
12608 }
12609
12610 /*
12611 This is the situation after locating BI:
12612
12613 ===|=== before image ====|=== after image ===|===
12614 ^ ^
12615 m_curr_row m_curr_row_end
12616
12617 BI found in the table is stored in record[0]. We copy it to record[1]
12618 and unpack AI to record[0].
12619 */
12620
12621 219111 store_record(m_table, record[1]);
12622
12623 219111 m_curr_row = m_curr_row_end;
12624 /* this also updates m_curr_row_end */
12625
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 218994 times.
219111 if ((error = unpack_current_row(rli, &m_cols_ai, true /*is AI*/)))
12626 117 return error;
12627
12628 // Invoke check constraints on the unpacked row.
12629
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 218993 times.
218994 if (invoke_table_check_constraints(thd, m_table))
12630 1 return ER_CHECK_CONSTRAINT_VIOLATED;
12631
12632 /*
12633 Now we have the right row to update. The old row (the one we're
12634 looking for) is in record[1] and the new row is in record[0].
12635 */
12636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 218993 times.
218993 DBUG_PRINT("info", ("Updating row in table"));
12637 218993 DBUG_DUMP("old record", m_table->record[1], m_table->s->reclength);
12638 218993 DBUG_DUMP("new values", m_table->record[0], m_table->s->reclength);
12639
12640 218993 m_table->mark_columns_per_binlog_row_image(thd);
12641 218993 error = m_table->file->ha_update_row(m_table->record[1], m_table->record[0]);
12642
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 218989 times.
218990 if (error == HA_ERR_RECORD_IS_THE_SAME) error = 0;
12643 218990 m_table->default_column_bitmaps();
12644
12645 218990 return error;
12646 }
12647
12648 #endif /* defined(MYSQL_SERVER) */
12649
12650 #ifndef MYSQL_SERVER
12651 4856 void Update_rows_log_event::print(FILE *file,
12652 PRINT_EVENT_INFO *print_event_info) const {
12653 4856 Rows_log_event::print_helper(file, print_event_info);
12654 4856 }
12655 #endif
12656
12657 25 Incident_log_event::Incident_log_event(
12658 25 const char *buf, const Format_description_event *description_event)
12659 : binary_log::Incident_event(buf, description_event),
12660
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
25 Log_event(header(), footer()) {
12661
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 DBUG_TRACE;
12662 25 }
12663
12664 122 Incident_log_event::~Incident_log_event() {
12665
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 3 times.
72 if (message) bapi_free(message);
12666 122 }
12667
12668 15 const char *Incident_log_event::description() const {
12669 static const char *const description[] = {"NOTHING", // Not used
12670 "LOST_EVENTS"};
12671
12672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 DBUG_PRINT("info", ("incident: %d", incident));
12673
12674 15 return description[incident];
12675 }
12676
12677 #ifdef MYSQL_SERVER
12678 9 int Incident_log_event::pack_info(Protocol *protocol) {
12679 char buf[256];
12680 size_t bytes;
12681
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (message_length > 0)
12682
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 bytes = snprintf(buf, sizeof(buf), "#%d (%s)", incident, description());
12683 else
12684 bytes = snprintf(buf, sizeof(buf), "#%d (%s): %s", incident, description(),
12685 message);
12686
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 protocol->store_string(buf, bytes, &my_charset_bin);
12687 9 return 0;
12688 }
12689 #endif
12690
12691 #ifndef MYSQL_SERVER
12692 1 void Incident_log_event::print(FILE *,
12693 PRINT_EVENT_INFO *print_event_info) const {
12694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (print_event_info->short_form) return;
12695
12696 1 print_header(&print_event_info->head_cache, print_event_info, false);
12697 1 my_b_printf(
12698 &print_event_info->head_cache,
12699 "\n# Incident: %s\nRELOAD DATABASE; # Shall generate syntax error\n",
12700 description());
12701 }
12702 #endif
12703
12704 #if defined(MYSQL_SERVER)
12705 8 int Incident_log_event::do_apply_event(Relay_log_info const *rli) {
12706
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 DBUG_TRACE;
12707
12708 /*
12709 It is not necessary to do GTID related check if the error
12710 'ER_SLAVE_INCIDENT' is ignored.
12711 */
12712
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
8 if (ignored_error_code(ER_SLAVE_INCIDENT)) {
12713
3/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2 DBUG_PRINT("info", ("Ignoring Incident"));
12714
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 mysql_bin_log.gtid_end_transaction(thd);
12715 2 return 0;
12716 }
12717
12718
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 enum_gtid_statement_status state = gtid_pre_statement_checks(thd);
12719
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 if (state == GTID_STATEMENT_EXECUTE) {
12720
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (gtid_pre_statement_post_implicit_commit_checks(thd))
12721 state = GTID_STATEMENT_CANCEL;
12722 }
12723
12724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (state == GTID_STATEMENT_CANCEL) {
12725 uint error = thd->get_stmt_da()->mysql_errno();
12726 assert(error != 0);
12727 rli->report(ERROR_LEVEL, error, "Error executing incident event: '%s'",
12728 thd->get_stmt_da()->message_text());
12729 thd->is_slave_error = true;
12730 return -1;
12731
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 } else if (state == GTID_STATEMENT_SKIP) {
12732 /*
12733 Make slave skip the Incident event through general commands of GTID
12734 i.e. 'set gtid_next=<GTID>; begin; commit;'.
12735 */
12736 1 return 0;
12737 }
12738
12739
3/6
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
5 rli->report(ERROR_LEVEL, ER_SLAVE_INCIDENT, ER_THD(thd, ER_SLAVE_INCIDENT),
12740
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 description(), message_length > 0 ? message : "<none>");
12741 5 return 1;
12742 8 }
12743
12744 10 bool Incident_log_event::write_data_header(Basic_ostream *ostream) {
12745
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 DBUG_TRACE;
12746
3/8
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10 DBUG_PRINT("enter", ("incident: %d", incident));
12747 uchar buf[sizeof(int16)];
12748 10 int2store(buf, (int16)incident);
12749
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
20 return wrapper_my_b_safe_write(ostream, buf, sizeof(buf));
12750 10 }
12751
12752 /*
12753 Stores string to an output stream.
12754
12755 Writes str to file in the following format:
12756 1. Stores length using only one byte (255 maximum value);
12757 2. Stores complete str.
12758 */
12759
12760 81 static bool write_str_at_most_255_bytes(Basic_ostream *ostream, const char *str,
12761 uint length) {
12762 uchar tmp[1];
12763
12764 81 tmp[0] = (uchar)length;
12765 return (
12766
3/6
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 81 times.
✗ Branch 5 not taken.
162 ostream->write(tmp, sizeof(tmp)) ||
12767
2/4
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
162 (length > 0 && ostream->write(pointer_cast<const uchar *>(str), length)));
12768 }
12769
12770 10 bool Incident_log_event::write_data_body(Basic_ostream *ostream) {
12771 uchar tmp[1];
12772
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 DBUG_TRACE;
12773 10 tmp[0] = (uchar)message_length;
12774
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 crc = checksum_crc32(crc, (uchar *)tmp, 1);
12775
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (message_length > 0) {
12776
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 crc = checksum_crc32(crc, (uchar *)message, message_length);
12777 // todo: report a bug on write_str accepts uint but treats it as uchar
12778 }
12779
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
20 return write_str_at_most_255_bytes(ostream, message, (uint)message_length);
12780 10 }
12781 #endif
12782
12783 250 Ignorable_log_event::Ignorable_log_event(
12784 2 const char *buf, const Format_description_event *descr_event)
12785 : binary_log::Ignorable_event(buf, descr_event),
12786
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
250 Log_event(header(), footer()) {
12787
1/2
✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
250 DBUG_TRACE;
12788 250 }
12789
12790 394 Ignorable_log_event::~Ignorable_log_event() = default;
12791
12792 #ifdef MYSQL_SERVER
12793 /* Pack info for its unrecognized ignorable event */
12794 int Ignorable_log_event::pack_info(Protocol *protocol) {
12795 char buf[256];
12796 size_t bytes;
12797 bytes = snprintf(buf, sizeof(buf), "# Unrecognized ignorable event");
12798 protocol->store_string(buf, bytes, &my_charset_bin);
12799 return 0;
12800 }
12801 #endif
12802
12803 #ifndef MYSQL_SERVER
12804 /* Print for its unrecognized ignorable event */
12805 void Ignorable_log_event::print(FILE *,
12806 PRINT_EVENT_INFO *print_event_info) const {
12807 if (print_event_info->short_form) return;
12808
12809 print_header(&print_event_info->head_cache, print_event_info, false);
12810 my_b_printf(&print_event_info->head_cache, "\tIgnorable\n");
12811 my_b_printf(&print_event_info->head_cache,
12812 "# Unrecognized ignorable event\n");
12813 }
12814 #endif
12815
12816 248 Rows_query_log_event::Rows_query_log_event(
12817 248 const char *buf, const Format_description_event *descr_event)
12818 : binary_log::Ignorable_event(buf, descr_event),
12819 Ignorable_log_event(buf, descr_event),
12820
2/4
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 124 times.
✗ Branch 3 not taken.
248 binary_log::Rows_query_event(buf, descr_event) {
12821
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
248 DBUG_TRACE;
12822 }
12823
12824 #ifdef MYSQL_SERVER
12825 45 int Rows_query_log_event::pack_info(Protocol *protocol) {
12826 char *buf;
12827 size_t bytes;
12828 45 size_t len = sizeof("# ") + strlen(m_rows_query);
12829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if (!(buf = (char *)my_malloc(key_memory_log_event, len, MYF(MY_WME))))
12830 return 1;
12831 45 bytes = snprintf(buf, len, "# %s", m_rows_query);
12832 45 protocol->store_string(buf, bytes, &my_charset_bin);
12833 45 my_free(buf);
12834 45 return 0;
12835 }
12836 #endif
12837
12838 #ifndef MYSQL_SERVER
12839 28 void Rows_query_log_event::print(FILE *,
12840 PRINT_EVENT_INFO *print_event_info) const {
12841
3/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 1 times.
28 if (!print_event_info->short_form && print_event_info->verbose > 1) {
12842 27 IO_CACHE *const head = &print_event_info->head_cache;
12843 27 IO_CACHE *const body = &print_event_info->body_cache;
12844 27 char *token = nullptr, *saveptr = nullptr;
12845 27 char *rows_query_copy = nullptr;
12846 27 if (!(rows_query_copy =
12847
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
27 my_strdup(key_memory_log_event, m_rows_query, MYF(MY_WME))))
12848 return;
12849
12850
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 print_header(head, print_event_info, false);
12851
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 my_b_printf(head, "\tRows_query\n");
12852 /*
12853 Prefix every line of a multi-line query with '#' to prevent the
12854 statement from being executed when binary log will be processed
12855 using 'mysqlbinlog --verbose --verbose'.
12856 */
12857
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 27 times.
56 for (token = my_strtok_r(rows_query_copy, "\n", &saveptr); token;
12858 29 token = my_strtok_r(nullptr, "\n", &saveptr))
12859
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 my_b_printf(head, "# %s\n", token);
12860
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 my_free(rows_query_copy);
12861
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 print_base64(body, print_event_info, true);
12862 }
12863 }
12864 #endif
12865
12866 #if defined(MYSQL_SERVER)
12867 71 bool Rows_query_log_event::write_data_body(Basic_ostream *ostream) {
12868
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 DBUG_TRACE;
12869 /*
12870 m_rows_query length will be stored using only one byte, but on read
12871 that length will be ignored and the complete query will be read.
12872 */
12873 142 return write_str_at_most_255_bytes(ostream, m_rows_query,
12874
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
142 strlen(m_rows_query));
12875 71 }
12876
12877 50 int Rows_query_log_event::do_apply_event(Relay_log_info const *rli) {
12878
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 DBUG_TRACE;
12879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 assert(rli->info_thd == thd);
12880 /* Set query for writing Rows_query log event into binlog later.*/
12881
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 thd->set_query(m_rows_query, strlen(m_rows_query));
12882
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 thd->set_query_for_display(m_rows_query, strlen(m_rows_query));
12883
12884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 assert(rli->rows_query_ev == nullptr);
12885
12886 50 const_cast<Relay_log_info *>(rli)->rows_query_ev = this;
12887 /* Tell worker not to free the event */
12888 50 worker = nullptr;
12889
12890
3/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 47 times.
50 DBUG_EXECUTE_IF("error_on_rows_query_event_apply", { return 1; };);
12891 47 return 0;
12892 50 }
12893 #endif
12894
12895 const char *Gtid_log_event::SET_STRING_PREFIX = "SET @@SESSION.GTID_NEXT= '";
12896
12897 3793489 Gtid_log_event::Gtid_log_event(
12898 3793489 const char *buffer, const Format_description_event *description_event)
12899 : binary_log::Gtid_event(buffer, description_event),
12900
1/2
✓ Branch 0 taken 3763771 times.
✗ Branch 1 not taken.
3793489 Log_event(header(), footer()) {
12901
1/2
✓ Branch 0 taken 3793492 times.
✗ Branch 1 not taken.
3793491 DBUG_TRACE;
12902
3/4
✓ Branch 0 taken 3763771 times.
✓ Branch 1 taken 29720 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3763771 times.
3793492 if (!is_valid()) return;
12903
12904 #ifndef NDEBUG
12905 3793491 uint8_t const common_header_len = description_event->common_header_len;
12906 uint8 const post_header_len =
12907 3793491 buffer[EVENT_TYPE_OFFSET] == binary_log::ANONYMOUS_GTID_LOG_EVENT
12908
2/2
✓ Branch 0 taken 3549073 times.
✓ Branch 1 taken 244418 times.
7586982 ? description_event
12909 3549073 ->post_header_len[binary_log::ANONYMOUS_GTID_LOG_EVENT - 1]
12910 244418 : description_event->post_header_len[binary_log::GTID_LOG_EVENT - 1];
12911
3/8
✓ Branch 0 taken 3793490 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3793490 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3793490 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
3793491 DBUG_PRINT("info",
12912 ("event_len: %zu; common_header_len: %d; post_header_len: %d",
12913 header()->data_written, common_header_len, post_header_len));
12914 #endif
12915
12916 3793490 spec.type = get_type_code() == binary_log::ANONYMOUS_GTID_LOG_EVENT
12917
2/2
✓ Branch 0 taken 3549071 times.
✓ Branch 1 taken 244418 times.
3793489 ? ANONYMOUS_GTID
12918 : ASSIGNED_GTID;
12919 3793489 sid.copy_from((uchar *)Uuid_parent_struct.bytes);
12920 3793490 spec.gtid.sidno = gtid_info_struct.rpl_gtid_sidno;
12921 3793490 spec.gtid.gno = gtid_info_struct.rpl_gtid_gno;
12922
1/2
✓ Branch 0 taken 3793491 times.
✗ Branch 1 not taken.
3793490 }
12923
12924 #ifdef MYSQL_SERVER
12925 5927063 Gtid_log_event::Gtid_log_event(THD *thd_arg, bool using_trans,
12926 int64 last_committed_arg,
12927 int64 sequence_number_arg,
12928 bool may_have_sbr_stmts_arg,
12929 ulonglong original_commit_timestamp_arg,
12930 ulonglong immediate_commit_timestamp_arg,
12931 uint32_t original_server_version_arg,
12932 5927063 uint32_t immediate_server_version_arg)
12933 : binary_log::Gtid_event(
12934 last_committed_arg, sequence_number_arg, may_have_sbr_stmts_arg,
12935 original_commit_timestamp_arg, immediate_commit_timestamp_arg,
12936 original_server_version_arg, immediate_server_version_arg),
12937 Log_event(thd_arg,
12938 5927063 thd_arg->variables.gtid_next.type == ANONYMOUS_GTID
12939 ? LOG_EVENT_IGNORABLE_F
12940 : 0,
12941 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
12942 : Log_event::EVENT_STMT_CACHE,
12943
5/6
✓ Branch 0 taken 5445255 times.
✓ Branch 1 taken 481808 times.
✓ Branch 2 taken 270645 times.
✓ Branch 3 taken 5656418 times.
✓ Branch 4 taken 5927063 times.
✗ Branch 5 not taken.
5927063 Log_event::EVENT_NORMAL_LOGGING, header(), footer()) {
12944
1/2
✓ Branch 0 taken 5927063 times.
✗ Branch 1 not taken.
5927063 DBUG_TRACE;
12945
2/2
✓ Branch 0 taken 203805 times.
✓ Branch 1 taken 5723258 times.
5927063 if (thd->owned_gtid.sidno > 0) {
12946 203805 spec.set(thd->owned_gtid);
12947 203805 sid = thd->owned_sid;
12948 } else {
12949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5723258 times.
5723258 assert(thd->owned_gtid.sidno == THD::OWNED_SIDNO_ANONYMOUS);
12950 5723258 spec.set_anonymous();
12951 5723258 spec.gtid.clear();
12952 5723258 sid.clear();
12953 }
12954
12955 5927063 Log_event_type event_type =
12956
2/2
✓ Branch 0 taken 5723258 times.
✓ Branch 1 taken 203805 times.
5927063 (spec.type == ANONYMOUS_GTID ? binary_log::ANONYMOUS_GTID_LOG_EVENT
12957 : binary_log::GTID_LOG_EVENT);
12958 5927063 common_header->type_code = event_type;
12959
12960 #ifndef NDEBUG
12961 char buf[MAX_SET_STRING_LENGTH + 1];
12962
1/2
✓ Branch 0 taken 5927063 times.
✗ Branch 1 not taken.
5927063 to_string(buf);
12963
5/8
✓ Branch 0 taken 5927063 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5927063 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 106 times.
✓ Branch 5 taken 5926957 times.
✓ Branch 6 taken 106 times.
✗ Branch 7 not taken.
5927063 DBUG_PRINT("info", ("%s", buf));
12964 #endif
12965 5927063 common_header->set_is_valid(true);
12966 5927063 }
12967
12968 31063 Gtid_log_event::Gtid_log_event(
12969 uint32 server_id_arg, bool using_trans, int64 last_committed_arg,
12970 int64 sequence_number_arg, bool may_have_sbr_stmts_arg,
12971 ulonglong original_commit_timestamp_arg,
12972 ulonglong immediate_commit_timestamp_arg, const Gtid_specification spec_arg,
12973 31063 uint32_t original_server_version_arg, uint32_t immediate_server_version_arg)
12974 : binary_log::Gtid_event(
12975 last_committed_arg, sequence_number_arg, may_have_sbr_stmts_arg,
12976 original_commit_timestamp_arg, immediate_commit_timestamp_arg,
12977 original_server_version_arg, immediate_server_version_arg),
12978 Log_event(header(), footer(),
12979 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
12980 : Log_event::EVENT_STMT_CACHE,
12981
3/4
✓ Branch 0 taken 17521 times.
✓ Branch 1 taken 13542 times.
✓ Branch 2 taken 31063 times.
✗ Branch 3 not taken.
31063 Log_event::EVENT_NORMAL_LOGGING) {
12982
1/2
✓ Branch 0 taken 31063 times.
✗ Branch 1 not taken.
31063 DBUG_TRACE;
12983 31063 server_id = server_id_arg;
12984 31063 common_header->unmasked_server_id = server_id_arg;
12985 31063 common_header->set_is_valid(true);
12986
12987
2/2
✓ Branch 0 taken 31062 times.
✓ Branch 1 taken 1 times.
31063 if (spec_arg.type == ASSIGNED_GTID) {
12988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31062 times.
31062 assert(spec_arg.gtid.sidno > 0);
12989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31062 times.
31062 assert(spec_arg.gtid.gno > 0);
12990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31062 times.
31062 assert(spec_arg.gtid.gno < GNO_END);
12991
2/4
✓ Branch 0 taken 31062 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 31062 times.
31062 if (spec_arg.gtid.gno <= 0 || spec_arg.gtid.gno >= GNO_END)
12992 common_header->set_is_valid(false);
12993 31062 spec.set(spec_arg.gtid);
12994
1/2
✓ Branch 0 taken 31062 times.
✗ Branch 1 not taken.
31062 global_sid_lock->rdlock();
12995
1/2
✓ Branch 0 taken 31062 times.
✗ Branch 1 not taken.
31062 sid = global_sid_map->sidno_to_sid(spec_arg.gtid.sidno);
12996
1/2
✓ Branch 0 taken 31062 times.
✗ Branch 1 not taken.
31062 global_sid_lock->unlock();
12997 } else {
12998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(spec_arg.type == ANONYMOUS_GTID);
12999 1 spec.set_anonymous();
13000 1 spec.gtid.clear();
13001 1 sid.clear();
13002 1 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13003 }
13004
13005 31063 Log_event_type event_type =
13006
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 31062 times.
31063 (spec.type == ANONYMOUS_GTID ? binary_log::ANONYMOUS_GTID_LOG_EVENT
13007 : binary_log::GTID_LOG_EVENT);
13008 31063 common_header->type_code = event_type;
13009
13010 #ifndef NDEBUG
13011 char buf[MAX_SET_STRING_LENGTH + 1];
13012
1/2
✓ Branch 0 taken 31063 times.
✗ Branch 1 not taken.
31063 to_string(buf);
13013
5/8
✓ Branch 0 taken 31063 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31063 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 31061 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
31063 DBUG_PRINT("info", ("%s", buf));
13014 #endif
13015 31063 }
13016
13017 23322 int Gtid_log_event::pack_info(Protocol *protocol) {
13018 char buffer[MAX_SET_STRING_LENGTH + 1];
13019
1/2
✓ Branch 0 taken 23322 times.
✗ Branch 1 not taken.
23322 size_t len = to_string(buffer);
13020
1/2
✓ Branch 0 taken 23322 times.
✗ Branch 1 not taken.
23322 protocol->store_string(buffer, len, &my_charset_bin);
13021 23322 return 0;
13022 }
13023 #endif // MYSQL_SERVER
13024
13025 6004144 size_t Gtid_log_event::to_string(char *buf) const {
13026 6004144 char *p = buf;
13027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6004144 times.
6004144 assert(strlen(SET_STRING_PREFIX) == SET_STRING_PREFIX_LENGTH);
13028 6004144 strcpy(p, SET_STRING_PREFIX);
13029 6004144 p += SET_STRING_PREFIX_LENGTH;
13030 6004144 p += spec.to_string(&sid, p);
13031 6004144 *p++ = '\'';
13032 6004144 *p = '\0';
13033 6004144 return p - buf;
13034 }
13035
13036 #ifndef MYSQL_SERVER
13037 22696 void Gtid_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
13038 char buffer[MAX_SET_STRING_LENGTH + 1];
13039 22696 IO_CACHE *const head = &print_event_info->head_cache;
13040
2/2
✓ Branch 0 taken 21841 times.
✓ Branch 1 taken 855 times.
22696 if (!print_event_info->short_form) {
13041
1/2
✓ Branch 0 taken 21841 times.
✗ Branch 1 not taken.
21841 print_header(head, print_event_info, false);
13042
3/4
✓ Branch 0 taken 8234 times.
✓ Branch 1 taken 13607 times.
✓ Branch 2 taken 21841 times.
✗ Branch 3 not taken.
43682 my_b_printf(head,
13043 "\t%s\tlast_committed=%llu\tsequence_number=%llu\t"
13044 "rbr_only=%s\t"
13045 "original_committed_timestamp=%llu\t"
13046 "immediate_commit_timestamp=%llu\t"
13047 "transaction_length=%llu\n",
13048 21841 get_type_code() == binary_log::GTID_LOG_EVENT
13049 ? "GTID"
13050 : "Anonymous_GTID",
13051 21841 last_committed, sequence_number,
13052 21841 may_have_sbr_stmts ? "no" : "yes", original_commit_timestamp,
13053
2/2
✓ Branch 0 taken 10861 times.
✓ Branch 1 taken 10980 times.
21841 immediate_commit_timestamp, transaction_length);
13054 }
13055
13056 /*
13057 The applier thread can always use "READ COMMITTED" isolation for
13058 transactions containing only RBR events (Table_map + Rows).
13059
13060 This would prevent some deadlock issues because InnoDB doesn't
13061 acquire GAP locks in "READ COMMITTED" isolation level since
13062 MySQL 5.7.18.
13063 */
13064
2/2
✓ Branch 0 taken 10982 times.
✓ Branch 1 taken 11714 times.
22696 if (!may_have_sbr_stmts) {
13065 10982 my_b_printf(head,
13066 "/*!50718 SET TRANSACTION ISOLATION LEVEL "
13067 "READ COMMITTED*/%s\n",
13068
1/2
✓ Branch 0 taken 10982 times.
✗ Branch 1 not taken.
10982 print_event_info->delimiter);
13069 }
13070
13071 /*
13072 We always print the original commit timestamp in order to make
13073 dumps from binary logs generated on servers without this info on
13074 GTID events to print "0" (not known) as the session value.
13075 */
13076 char llbuf[22];
13077
13078 char immediate_commit_timestamp_str[256];
13079 char original_commit_timestamp_str[256];
13080
13081 22696 microsecond_timestamp_to_str(immediate_commit_timestamp,
13082 immediate_commit_timestamp_str);
13083 22696 microsecond_timestamp_to_str(original_commit_timestamp,
13084 original_commit_timestamp_str);
13085
13086
1/2
✓ Branch 0 taken 22696 times.
✗ Branch 1 not taken.
22696 my_b_printf(head, "# original_commit_timestamp=%s (%s)\n",
13087
1/2
✓ Branch 0 taken 22696 times.
✗ Branch 1 not taken.
22696 llstr(original_commit_timestamp, llbuf),
13088 original_commit_timestamp_str);
13089
1/2
✓ Branch 0 taken 22696 times.
✗ Branch 1 not taken.
22696 my_b_printf(head, "# immediate_commit_timestamp=%s (%s)\n",
13090
1/2
✓ Branch 0 taken 22696 times.
✗ Branch 1 not taken.
22696 llstr(immediate_commit_timestamp, llbuf),
13091 immediate_commit_timestamp_str);
13092
13093
3/4
✓ Branch 0 taken 22696 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22690 times.
✓ Branch 3 taken 6 times.
22696 if (DBUG_EVALUATE_IF("do_not_write_rpl_OCT", false, true)) {
13094
1/2
✓ Branch 0 taken 22690 times.
✗ Branch 1 not taken.
22690 my_b_printf(
13095 head, "/*!80001 SET @@session.original_commit_timestamp=%s*/%s\n",
13096
1/2
✓ Branch 0 taken 22690 times.
✗ Branch 1 not taken.
22690 llstr(original_commit_timestamp, llbuf), print_event_info->delimiter);
13097 }
13098
13099 22696 my_b_printf(head, "/*!80014 SET @@session.original_server_version=%u*/%s\n",
13100
1/2
✓ Branch 0 taken 22696 times.
✗ Branch 1 not taken.
22696 original_server_version, print_event_info->delimiter);
13101
13102 22696 my_b_printf(head, "/*!80014 SET @@session.immediate_server_version=%u*/%s\n",
13103
1/2
✓ Branch 0 taken 22696 times.
✗ Branch 1 not taken.
22696 immediate_server_version, print_event_info->delimiter);
13104
13105
1/2
✓ Branch 0 taken 22696 times.
✗ Branch 1 not taken.
22696 to_string(buffer);
13106
1/2
✓ Branch 0 taken 22696 times.
✗ Branch 1 not taken.
22696 my_b_printf(head, "%s%s\n", buffer, print_event_info->delimiter);
13107 22696 }
13108 #endif
13109
13110 #ifdef MYSQL_SERVER
13111 5958264 uint32 Gtid_log_event::write_post_header_to_memory(uchar *buffer) {
13112
1/2
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
5958264 DBUG_TRACE;
13113 5958264 uchar *ptr_buffer = buffer;
13114
13115 /* Encode the GTID flags */
13116 5958264 uchar gtid_flags = 0;
13117 5335627 gtid_flags |=
13118
2/2
✓ Branch 0 taken 622637 times.
✓ Branch 1 taken 5335627 times.
5958264 may_have_sbr_stmts ? binary_log::Gtid_event::FLAG_MAY_HAVE_SBR : 0;
13119 5958264 *ptr_buffer = gtid_flags;
13120 5958264 ptr_buffer += ENCODED_FLAG_LENGTH;
13121
13122 #ifndef NDEBUG
13123 char buf[binary_log::Uuid::TEXT_LENGTH + 1];
13124
1/2
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
5958264 sid.to_string(buf);
13125
5/8
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5958264 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 108 times.
✓ Branch 5 taken 5958156 times.
✓ Branch 6 taken 108 times.
✗ Branch 7 not taken.
5958264 DBUG_PRINT("info", ("sid=%s sidno=%d gno=%" PRId64, buf, spec.gtid.sidno,
13126 spec.gtid.gno));
13127 #endif
13128
13129 5958264 sid.copy_to(ptr_buffer);
13130 5958264 ptr_buffer += ENCODED_SID_LENGTH;
13131
13132 #ifndef NDEBUG
13133
2/4
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5958264 times.
5958264 if (DBUG_EVALUATE_IF("send_invalid_gno_to_replica", true, false))
13134 int8store(ptr_buffer, GNO_END);
13135 else
13136 #endif
13137 5958264 int8store(ptr_buffer, spec.gtid.gno);
13138 5958264 ptr_buffer += ENCODED_GNO_LENGTH;
13139
13140 5958264 *ptr_buffer = LOGICAL_TIMESTAMP_TYPECODE;
13141 5958264 ptr_buffer += LOGICAL_TIMESTAMP_TYPECODE_LENGTH;
13142
13143
4/6
✓ Branch 0 taken 3808 times.
✓ Branch 1 taken 5954456 times.
✓ Branch 2 taken 3808 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5954456 times.
5958264 assert((sequence_number == 0 && last_committed == 0) ||
13144 (sequence_number > last_committed));
13145
5/6
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3259 times.
✓ Branch 3 taken 5955005 times.
✓ Branch 4 taken 3231 times.
✓ Branch 5 taken 28 times.
5958264 DBUG_EXECUTE_IF("set_commit_parent_100", {
13146 last_committed =
13147 max<int64>(sequence_number > 1 ? 1 : 0, sequence_number - 100);
13148 });
13149
5/6
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 5958231 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 6 times.
5958264 DBUG_EXECUTE_IF("set_commit_parent_150", {
13150 last_committed =
13151 max<int64>(sequence_number > 1 ? 1 : 0, sequence_number - 150);
13152 });
13153
3/4
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5958263 times.
5958264 DBUG_EXECUTE_IF("feign_commit_parent", { last_committed = sequence_number; });
13154 5958264 int8store(ptr_buffer, last_committed);
13155 5958264 int8store(ptr_buffer + 8, sequence_number);
13156 5958264 ptr_buffer += LOGICAL_TIMESTAMP_LENGTH;
13157
13158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5958264 times.
5958264 assert(ptr_buffer == (buffer + POST_HEADER_LENGTH));
13159
13160 5958264 return POST_HEADER_LENGTH;
13161 5958264 }
13162
13163 #ifdef MYSQL_SERVER
13164 5958264 bool Gtid_log_event::write_data_header(Basic_ostream *ostream) {
13165
1/2
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
5958264 DBUG_TRACE;
13166 uchar buffer[POST_HEADER_LENGTH];
13167
1/2
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
5958264 write_post_header_to_memory(buffer);
13168
1/2
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
11916528 return wrapper_my_b_safe_write(ostream, (uchar *)buffer, POST_HEADER_LENGTH);
13169 5958264 }
13170
13171 5958264 uint32 Gtid_log_event::write_body_to_memory(uchar *buffer) {
13172
1/2
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
5958264 DBUG_TRACE;
13173
3/4
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5958262 times.
5958264 DBUG_EXECUTE_IF("do_not_write_rpl_timestamps", return 0;);
13174 5958262 uchar *ptr_buffer = buffer;
13175
13176 /*
13177 We want to modify immediate_commit_timestamp with the flag written
13178 in the highest bit(MSB). At the same time, we also want to have the original
13179 value to be able to use in if() later, so we use a temporary variable here.
13180 */
13181 5958262 ulonglong immediate_commit_timestamp_with_flag = immediate_commit_timestamp;
13182
13183 // Transaction did not originate at this server, set highest bit to hint this.
13184
2/2
✓ Branch 0 taken 337510 times.
✓ Branch 1 taken 5620752 times.
5958262 if (immediate_commit_timestamp != original_commit_timestamp)
13185 337510 immediate_commit_timestamp_with_flag |=
13186 (1ULL << ENCODED_COMMIT_TIMESTAMP_LENGTH);
13187 else // Clear highest bit(MSB)
13188 5620752 immediate_commit_timestamp_with_flag &=
13189 ~(1ULL << ENCODED_COMMIT_TIMESTAMP_LENGTH);
13190
13191 5958262 int7store(ptr_buffer, immediate_commit_timestamp_with_flag);
13192 5958262 ptr_buffer += IMMEDIATE_COMMIT_TIMESTAMP_LENGTH;
13193
13194
2/2
✓ Branch 0 taken 337510 times.
✓ Branch 1 taken 5620752 times.
5958262 if (immediate_commit_timestamp != original_commit_timestamp) {
13195 337510 int7store(ptr_buffer, original_commit_timestamp);
13196 337510 ptr_buffer += ORIGINAL_COMMIT_TIMESTAMP_LENGTH;
13197 }
13198
13199 // Write the transaction length information
13200
1/2
✓ Branch 0 taken 5958262 times.
✗ Branch 1 not taken.
5958262 uchar *ptr_after_length = net_store_length(ptr_buffer, transaction_length);
13201 5958262 ptr_buffer = ptr_after_length;
13202
13203 /*
13204 We want to modify immediate_server_version with the flag written to its MSB.
13205 At the same time, we also want to have the original value to be able to use
13206 it in if() later, so we use a temporary variable here.
13207 */
13208 5958262 uint32_t immediate_server_version_with_flag = immediate_server_version;
13209
13210
2/2
✓ Branch 0 taken 379 times.
✓ Branch 1 taken 5957883 times.
5958262 if (immediate_server_version != original_server_version)
13211 379 immediate_server_version_with_flag |=
13212 (1ULL << ENCODED_SERVER_VERSION_LENGTH);
13213 else // Clear MSB
13214 5957883 immediate_server_version_with_flag &=
13215 ~(1ULL << ENCODED_SERVER_VERSION_LENGTH);
13216
13217 5958262 int4store(ptr_buffer, immediate_server_version_with_flag);
13218 5958262 ptr_buffer += IMMEDIATE_SERVER_VERSION_LENGTH;
13219
13220
2/2
✓ Branch 0 taken 379 times.
✓ Branch 1 taken 5957883 times.
5958262 if (immediate_server_version != original_server_version) {
13221 379 int4store(ptr_buffer, original_server_version);
13222 379 ptr_buffer += ORIGINAL_SERVER_VERSION_LENGTH;
13223 }
13224
13225 5958262 return ptr_buffer - buffer;
13226 5958264 }
13227
13228 5958264 bool Gtid_log_event::write_data_body(Basic_ostream *ostream) {
13229
1/2
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
5958264 DBUG_TRACE;
13230 uchar buffer[MAX_DATA_LENGTH];
13231
1/2
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
5958264 uint32 len = write_body_to_memory(buffer);
13232
1/2
✓ Branch 0 taken 5958264 times.
✗ Branch 1 not taken.
11916528 return wrapper_my_b_safe_write(ostream, (uchar *)buffer, len);
13233 5958264 }
13234
13235 #endif // MYSQL_SERVER
13236
13237 327840 int Gtid_log_event::do_apply_event(Relay_log_info const *rli) {
13238
1/2
✓ Branch 0 taken 327862 times.
✗ Branch 1 not taken.
327840 DBUG_TRACE;
13239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 327862 times.
327862 assert(rli->info_thd == thd);
13240
13241 /*
13242 In rare cases it is possible that we already own a GTID (either
13243 ANONYMOUS or ASSIGNED_GTID). This can happen if a transaction was truncated
13244 in the middle in the relay log and then next relay log begins with a
13245 Gtid_log_events without closing the transaction context from the previous
13246 relay log. In this case the only sensible thing to do is to discard the
13247 truncated transaction and move on.
13248
13249 Note that when the applier is "GTID skipping" a transactions it
13250 owns nothing, but its gtid_next->type == ASSIGNED_GTID.
13251 */
13252 327862 const Gtid_specification *gtid_next = &thd->variables.gtid_next;
13253
4/6
✓ Branch 0 taken 327862 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 327864 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 327855 times.
655727 if (!thd->owned_gtid_is_empty() ||
13254
4/6
✓ Branch 0 taken 327865 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 327866 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 327856 times.
327864 (thd->owned_gtid_is_empty() && gtid_next->type == ASSIGNED_GTID)) {
13255 /*
13256 Slave will execute this code if a previous Gtid_log_event was applied
13257 but the GTID wasn't consumed yet (the transaction was not committed,
13258 nor rolled back, nor skipped).
13259 On a client session we cannot do consecutive SET GTID_NEXT without
13260 a COMMIT or a ROLLBACK in the middle.
13261 Applying this event without rolling back the current transaction may
13262 lead to problems, as a "BEGIN" event following this GTID will
13263 implicitly commit the "partial transaction" and will consume the
13264 GTID. If this "partial transaction" was left in the relay log by the
13265 IO thread restarting in the middle of a transaction, you could have
13266 the partial transaction being logged with the GTID on the slave,
13267 causing data corruption on replication.
13268 */
13269
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (thd->server_status & SERVER_STATUS_IN_TRANS) {
13270 /* This is not an error (XA is safe), just an information */
13271 rli->report(INFORMATION_LEVEL, 0,
13272 "Rolling back unfinished transaction (no COMMIT "
13273 "or ROLLBACK in relay log). A probable cause is partial "
13274 "transaction left on relay log because of restarting IO "
13275 "thread with auto-positioning protocol.");
13276 const_cast<Relay_log_info *>(rli)->cleanup_context(thd, true);
13277 }
13278
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 gtid_state->update_on_rollback(thd);
13279 }
13280
13281
1/2
✓ Branch 0 taken 327865 times.
✗ Branch 1 not taken.
327863 global_sid_lock->rdlock();
13282
13283 // make sure that sid has been converted to sidno
13284
2/2
✓ Branch 0 taken 58568 times.
✓ Branch 1 taken 269297 times.
327865 if (spec.type == ASSIGNED_GTID) {
13285
2/4
✓ Branch 0 taken 58567 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 58567 times.
58568 if (get_sidno(false) < 0) {
13286 global_sid_lock->unlock();
13287 return 1; // out of memory
13288 }
13289
4/4
✓ Branch 0 taken 269293 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 633 times.
✓ Branch 3 taken 268663 times.
538589 } else if ((spec.type == ANONYMOUS_GTID) &&
13290
3/4
✓ Branch 0 taken 269292 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 633 times.
✓ Branch 3 taken 268659 times.
269293 (rli->m_assign_gtids_to_anonymous_transactions_info.get_type() >
13291 Assign_gtids_to_anonymous_transactions_info::enum_type::
13292 AGAT_OFF)) {
13293
2/4
✓ Branch 0 taken 633 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 633 times.
633 assert(global_gtid_mode.get() == Gtid_mode::ON);
13294 633 spec.type = PRE_GENERATE_GTID;
13295 633 spec.gtid.sidno =
13296 633 rli->m_assign_gtids_to_anonymous_transactions_info.get_sidno();
13297 }
13298
13299 // set_gtid_next releases global_sid_lock
13300
3/4
✓ Branch 0 taken 327856 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 327854 times.
327863 if (set_gtid_next(thd, spec))
13301 // This can happen e.g. if gtid_mode is incompatible with spec.
13302 2 return 1;
13303
13304 /*
13305 Set the original_commit_timestamp.
13306 0 will be used if this event does not contain such information.
13307 */
13308
1/2
✓ Branch 0 taken 327864 times.
✗ Branch 1 not taken.
327854 enum_gtid_statement_status state = gtid_pre_statement_checks(thd);
13309 327864 thd->variables.original_commit_timestamp = original_commit_timestamp;
13310
1/2
✓ Branch 0 taken 327857 times.
✗ Branch 1 not taken.
327864 thd->set_original_commit_timestamp_for_slave_thread();
13311 /**
13312 Set the original/immediate server version.
13313 It will be set to UNKNOWN_SERVER_VERSION if the event does not contain such
13314 information.
13315 */
13316 327857 thd->variables.original_server_version = original_server_version;
13317 327857 thd->variables.immediate_server_version = immediate_server_version;
13318 327857 const_cast<Relay_log_info *>(rli)->started_processing(
13319
1/2
✓ Branch 0 taken 327867 times.
✗ Branch 1 not taken.
327857 thd->variables.gtid_next.gtid, original_commit_timestamp,
13320 immediate_commit_timestamp, state == GTID_STATEMENT_SKIP);
13321
13322 /*
13323 If the current transaction contains no changes logged with SBR
13324 we can assume this transaction as a pure row based replicated one.
13325
13326 Based on this assumption, we can set current transaction tx_isolation to
13327 READ COMMITTED in order to avoid concurrent transactions to be blocked by
13328 InnoDB gap locks.
13329
13330 The session tx_isolation will be restored:
13331 - When the transaction finishes with QUERY(COMMIT|ROLLBACK),
13332 as the MySQL server does for ordinary user sessions;
13333 - When applying a Xid_log_event, after committing the transaction;
13334 - When applying a XA_prepare_log_event, after preparing the transaction;
13335 - When the applier needs to abort a transaction execution.
13336
13337 Notice that when a transaction is being "gtid skipped", its statements are
13338 not actually executed (see mysql_execute_command()). So, the call to the
13339 function that would restore the tx_isolation after finishing the transaction
13340 may not happen.
13341 */
13342
11/14
✓ Branch 0 taken 327863 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 327864 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 170486 times.
✓ Branch 5 taken 157378 times.
✓ Branch 6 taken 170116 times.
✓ Branch 7 taken 370 times.
✓ Branch 8 taken 170119 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 167983 times.
✓ Branch 11 taken 2136 times.
✓ Branch 12 taken 167982 times.
✓ Branch 13 taken 159884 times.
327867 if (DBUG_EVALUATE_IF(
13343 "force_trx_as_rbr_only", true,
13344 !may_have_sbr_stmts && thd->tx_isolation > ISO_READ_COMMITTED &&
13345 gtid_pre_statement_checks(thd) != GTID_STATEMENT_SKIP)) {
13346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167982 times.
167982 assert(thd->get_transaction()->is_empty(Transaction_ctx::STMT));
13347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167982 times.
167982 assert(thd->get_transaction()->is_empty(Transaction_ctx::SESSION));
13348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167982 times.
167982 assert(!thd->lock);
13349
3/8
✓ Branch 0 taken 167983 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 167981 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 167981 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
167982 DBUG_PRINT("info", ("setting tx_isolation to READ COMMITTED"));
13350
1/2
✓ Branch 0 taken 167966 times.
✗ Branch 1 not taken.
167981 set_tx_isolation(thd, ISO_READ_COMMITTED, true /*one_shot*/);
13351 }
13352
13353 327850 return 0;
13354 327852 }
13355
13356 732 int Gtid_log_event::do_update_pos(Relay_log_info *rli) {
13357 /*
13358 This event does not increment group positions. This means
13359 that if there is a failure after it has been processed,
13360 it will be automatically re-executed.
13361 */
13362 732 rli->inc_event_relay_log_pos();
13363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 732 times.
732 DBUG_EXECUTE_IF(
13364 "crash_after_update_pos_gtid",
13365 sql_print_information("Crashing crash_after_update_pos_gtid.");
13366 DBUG_SUICIDE(););
13367 732 return 0;
13368 }
13369
13370 328210 Log_event::enum_skip_reason Gtid_log_event::do_shall_skip(Relay_log_info *rli) {
13371 328210 return Log_event::continue_group(rli);
13372 }
13373 #endif // MYSQL_SERVER
13374
13375 5940835 void Gtid_log_event::set_trx_length_by_cache_size(ulonglong cache_size,
13376 bool is_checksum_enabled,
13377 int event_counter) {
13378 // Transaction content length
13379 5940835 transaction_length = cache_size;
13380
2/2
✓ Branch 0 taken 5926984 times.
✓ Branch 1 taken 13851 times.
5940835 if (is_checksum_enabled)
13381 5926984 transaction_length += event_counter * BINLOG_CHECKSUM_LEN;
13382
13383 // GTID length
13384 5940835 transaction_length += LOG_EVENT_HEADER_LEN;
13385 5940835 transaction_length += POST_HEADER_LENGTH;
13386 5940835 transaction_length += get_commit_timestamp_length();
13387 5940835 transaction_length += get_server_version_length();
13388
2/2
✓ Branch 0 taken 5926984 times.
✓ Branch 1 taken 13851 times.
5940835 transaction_length += is_checksum_enabled ? BINLOG_CHECKSUM_LEN : 0;
13389
13390 /*
13391 Notice that it is not possible to determine the transaction_length field
13392 size using pack.cc:net_length_size() since the length of the field itself
13393 must be added to the value.
13394
13395 Example: Suppose transaction_length is 250 without considering the
13396 transaction_length field. Using net_length_size(250) would return 1, but
13397 when adding the transaction_length field size to it (+1), the
13398 transaction_length becomes 251, and the field must be represented using two
13399 more bytes, so the correct transaction length must be in fact 253.
13400 */
13401 #ifndef NDEBUG
13402 5940835 ulonglong size_without_transaction_length = transaction_length;
13403 #endif
13404 // transaction_length will use at least TRANSACTION_LENGTH_MIN_LENGTH
13405 5940835 transaction_length += TRANSACTION_LENGTH_MIN_LENGTH;
13406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5940835 times.
5940835 assert(transaction_length - size_without_transaction_length == 1);
13407
2/2
✓ Branch 0 taken 5575684 times.
✓ Branch 1 taken 365151 times.
5940835 if (transaction_length >= 251ULL) {
13408 // transaction_length will use at least 3 bytes
13409 5575684 transaction_length += 2;
13410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5575684 times.
5575684 assert(transaction_length - size_without_transaction_length == 3);
13411
2/2
✓ Branch 0 taken 15798 times.
✓ Branch 1 taken 5559886 times.
5575684 if (transaction_length >= 65536ULL) {
13412 // transaction_length will use at least 4 bytes
13413 15798 transaction_length += 1;
13414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15798 times.
15798 assert(transaction_length - size_without_transaction_length == 4);
13415
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 15675 times.
15798 if (transaction_length >= 16777216ULL) {
13416 // transaction_length will use 9 bytes
13417 123 transaction_length += 5;
13418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 123 times.
123 assert(transaction_length - size_without_transaction_length == 9);
13419 }
13420 }
13421 }
13422 5940835 }
13423
13424 122083 rpl_sidno Gtid_log_event::get_sidno(bool need_lock) {
13425
2/2
✓ Branch 0 taken 63632 times.
✓ Branch 1 taken 58451 times.
122083 if (spec.gtid.sidno < 0) {
13426
2/2
✓ Branch 0 taken 63395 times.
✓ Branch 1 taken 237 times.
63632 if (need_lock)
13427 63395 global_sid_lock->rdlock();
13428 else
13429 237 global_sid_lock->assert_some_lock();
13430 63632 spec.gtid.sidno = global_sid_map->add_sid(sid);
13431
2/2
✓ Branch 0 taken 63395 times.
✓ Branch 1 taken 237 times.
63632 if (need_lock) global_sid_lock->unlock();
13432 }
13433 122094 return spec.gtid.sidno;
13434 }
13435
13436 124435 Previous_gtids_log_event::Previous_gtids_log_event(
13437 124435 const char *buf_arg, const Format_description_event *description_event)
13438 : binary_log::Previous_gtids_event(buf_arg, description_event),
13439
1/2
✓ Branch 0 taken 119926 times.
✗ Branch 1 not taken.
124435 Log_event(header(), footer()) {
13440
1/2
✓ Branch 0 taken 124435 times.
✗ Branch 1 not taken.
124435 DBUG_TRACE;
13441 124435 }
13442
13443 #ifdef MYSQL_SERVER
13444 84428 Previous_gtids_log_event::Previous_gtids_log_event(const Gtid_set *set)
13445 : binary_log::Previous_gtids_event(),
13446 Log_event(header(), footer(), Log_event::EVENT_NO_CACHE,
13447
1/2
✓ Branch 0 taken 84428 times.
✗ Branch 1 not taken.
84428 Log_event::EVENT_IMMEDIATE_LOGGING) {
13448
1/2
✓ Branch 0 taken 84428 times.
✗ Branch 1 not taken.
84428 DBUG_TRACE;
13449 84428 common_header->type_code = binary_log::PREVIOUS_GTIDS_LOG_EVENT;
13450 84428 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13451
1/2
✓ Branch 0 taken 84428 times.
✗ Branch 1 not taken.
84428 set->get_sid_map()->get_sid_lock()->assert_some_lock();
13452
1/2
✓ Branch 0 taken 84428 times.
✗ Branch 1 not taken.
84428 buf_size = set->get_encoded_length();
13453 uchar *buffer =
13454
1/2
✓ Branch 0 taken 84428 times.
✗ Branch 1 not taken.
84428 (uchar *)my_malloc(key_memory_log_event, buf_size, MYF(MY_WME));
13455
1/2
✓ Branch 0 taken 84428 times.
✗ Branch 1 not taken.
84428 if (buffer != nullptr) {
13456
1/2
✓ Branch 0 taken 84428 times.
✗ Branch 1 not taken.
84428 set->encode(buffer);
13457 84428 register_temp_buf((char *)buffer);
13458 }
13459 84428 buf = buffer;
13460 // if buf is empty, is_valid will be false
13461 84428 common_header->set_is_valid(buf != nullptr);
13462 84428 }
13463
13464 3888 int Previous_gtids_log_event::pack_info(Protocol *protocol) {
13465 3888 size_t length = 0;
13466
1/2
✓ Branch 0 taken 3888 times.
✗ Branch 1 not taken.
3888 char *str = get_str(&length, &Gtid_set::default_string_format);
13467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3888 times.
3888 if (str == nullptr) return 1;
13468
1/2
✓ Branch 0 taken 3888 times.
✗ Branch 1 not taken.
3888 protocol->store_string(str, length, &my_charset_bin);
13469
1/2
✓ Branch 0 taken 3888 times.
✗ Branch 1 not taken.
3888 my_free(str);
13470 3888 return 0;
13471 }
13472 #endif // MYSQL_SERVER
13473
13474 #ifndef MYSQL_SERVER
13475 1458 void Previous_gtids_log_event::print(FILE *,
13476 PRINT_EVENT_INFO *print_event_info) const {
13477 1458 IO_CACHE *const head = &print_event_info->head_cache;
13478 1458 char *str = get_str(nullptr, &Gtid_set::commented_string_format);
13479
1/2
✓ Branch 0 taken 1458 times.
✗ Branch 1 not taken.
1458 if (str != nullptr) {
13480
2/2
✓ Branch 0 taken 1294 times.
✓ Branch 1 taken 164 times.
1458 if (!print_event_info->short_form) {
13481 1294 print_header(head, print_event_info, false);
13482 1294 my_b_printf(head, "\tPrevious-GTIDs\n");
13483 }
13484 1458 my_b_printf(head, "%s\n", str);
13485 1458 my_free(str);
13486 }
13487 1458 }
13488 #endif
13489
13490 52148 int Previous_gtids_log_event::add_to_set(Gtid_set *target) const {
13491
1/2
✓ Branch 0 taken 52148 times.
✗ Branch 1 not taken.
52148 DBUG_TRACE;
13492 52148 size_t end_pos = 0;
13493
2/4
✓ Branch 0 taken 52148 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 52148 times.
52148 size_t add_size = DBUG_EVALUATE_IF("gtid_has_extra_data", 10, 0);
13494 /* Silently ignore additional unknown data at the end of the encoding */
13495
2/6
✓ Branch 0 taken 52148 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 52148 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
52148 PROPAGATE_REPORTED_ERROR_INT(
13496 target->add_gtid_encoding(buf, buf_size + add_size, &end_pos));
13497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52148 times.
52148 assert(end_pos <= buf_size);
13498 52148 return 0;
13499 52148 }
13500
13501 38163 char *Previous_gtids_log_event::get_str(
13502 size_t *length_p, const Gtid_set::String_format *string_format) const {
13503
1/2
✓ Branch 0 taken 38163 times.
✗ Branch 1 not taken.
38163 DBUG_TRACE;
13504
1/2
✓ Branch 0 taken 38163 times.
✗ Branch 1 not taken.
38163 Sid_map sid_map(nullptr);
13505
1/2
✓ Branch 0 taken 38163 times.
✗ Branch 1 not taken.
38163 Gtid_set set(&sid_map, nullptr);
13506
3/8
✓ Branch 0 taken 38163 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38163 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 38163 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
38163 DBUG_PRINT("info", ("temp_buf=%p buf=%p", temp_buf, buf));
13507
2/4
✓ Branch 0 taken 38163 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 38163 times.
38163 if (set.add_gtid_encoding(buf, buf_size) != RETURN_STATUS_OK) return nullptr;
13508
1/2
✓ Branch 0 taken 38163 times.
✗ Branch 1 not taken.
38163 set.dbug_print("set");
13509
1/2
✓ Branch 0 taken 38163 times.
✗ Branch 1 not taken.
38163 size_t length = set.get_string_length(string_format);
13510
3/8
✓ Branch 0 taken 38163 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38163 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 38163 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
38163 DBUG_PRINT("info", ("string length= %lu", (ulong)length));
13511
1/2
✓ Branch 0 taken 38163 times.
✗ Branch 1 not taken.
38163 char *str = (char *)my_malloc(key_memory_log_event, length + 1, MYF(MY_WME));
13512
1/2
✓ Branch 0 taken 38163 times.
✗ Branch 1 not taken.
38163 if (str != nullptr) {
13513
1/2
✓ Branch 0 taken 38163 times.
✗ Branch 1 not taken.
38163 set.to_string(str, false /*need_lock*/, string_format);
13514
2/2
✓ Branch 0 taken 3888 times.
✓ Branch 1 taken 34275 times.
38163 if (length_p != nullptr) *length_p = length;
13515 }
13516 38163 return str;
13517 38163 }
13518
13519 #ifdef MYSQL_SERVER
13520 84398 bool Previous_gtids_log_event::write_data_body(Basic_ostream *ostream) {
13521
1/2
✓ Branch 0 taken 84398 times.
✗ Branch 1 not taken.
84398 DBUG_TRACE;
13522
3/8
✓ Branch 0 taken 84398 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84398 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 84398 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
84398 DBUG_PRINT("info", ("size=%d", static_cast<int>(buf_size)));
13523
1/2
✓ Branch 0 taken 84398 times.
✗ Branch 1 not taken.
84398 bool ret = wrapper_my_b_safe_write(ostream, buf, buf_size);
13524 84398 return ret;
13525 84398 }
13526
13527 31963 int Previous_gtids_log_event::do_update_pos(Relay_log_info *rli) {
13528 31963 rli->inc_event_relay_log_pos();
13529 31963 return 0;
13530 }
13531
13532 /**************************************************************************
13533 Transaction_context_log_event methods
13534 **************************************************************************/
13535
13536 13774 Transaction_context_log_event::Transaction_context_log_event(
13537 const char *server_uuid_arg, bool using_trans, my_thread_id thread_id_arg,
13538 13774 bool is_gtid_specified_arg)
13539 : binary_log::Transaction_context_event(thread_id_arg,
13540 is_gtid_specified_arg),
13541 Log_event(header(), footer(),
13542 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
13543 : Log_event::EVENT_STMT_CACHE,
13544
3/4
✓ Branch 0 taken 13716 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 13774 times.
✗ Branch 3 not taken.
13774 Log_event::EVENT_NORMAL_LOGGING) {
13545
1/2
✓ Branch 0 taken 13774 times.
✗ Branch 1 not taken.
13774 DBUG_TRACE;
13546 13774 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13547 13774 server_uuid = nullptr;
13548
2/4
✓ Branch 0 taken 13774 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13774 times.
✗ Branch 3 not taken.
13774 sid_map = new Sid_map(nullptr);
13549
2/4
✓ Branch 0 taken 13774 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13774 times.
✗ Branch 3 not taken.
13774 snapshot_version = new Gtid_set(sid_map);
13550
13551 /*
13552 Copy global_sid_map to a local copy to avoid the acquisition
13553 of the global_sid_lock for operations on top of this snapshot
13554 version.
13555 The Sid_map and Gtid_executed must be read under the protection
13556 of MYSQL_BIN_LOG.LOCK_commit to avoid race conditions between
13557 ordered commits in the storage engine and gtid_state update.
13558 */
13559
2/4
✓ Branch 0 taken 13774 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13774 times.
13774 if (mysql_bin_log.get_gtid_executed(sid_map, snapshot_version)) goto err;
13560
13561
1/2
✓ Branch 0 taken 13774 times.
✗ Branch 1 not taken.
13774 server_uuid = my_strdup(key_memory_log_event, server_uuid_arg, MYF(MY_WME));
13562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13774 times.
13774 if (server_uuid == nullptr) goto err;
13563
13564 // These two fields are only populated on event decoding.
13565 // Encoding is done directly from snapshot_version field.
13566 13774 encoded_snapshot_version = nullptr;
13567 13774 encoded_snapshot_version_length = 0;
13568
13569 // Debug sync point for SQL threads.
13570
7/12
✓ Branch 0 taken 13774 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 13773 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
13774 DBUG_EXECUTE_IF(
13571 "debug.wait_after_set_snapshot_version_on_transaction_context_log_event",
13572 {
13573 const char act[] =
13574 "now wait_for "
13575 "signal.resume_after_set_snapshot_version_on_transaction_context_"
13576 "log_event";
13577 assert(opt_debug_sync_timeout > 0);
13578 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
13579 };);
13580
13581 13774 common_header->set_is_valid(true);
13582 13774 return;
13583
13584 err:
13585 common_header->set_is_valid(false);
13586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13774 times.
13774 }
13587 #endif // MYSQL_SERVER
13588
13589 28042 Transaction_context_log_event::Transaction_context_log_event(
13590 28042 const char *buffer, const Format_description_event *descr_event)
13591 : binary_log::Transaction_context_event(buffer, descr_event),
13592 Log_event(header(), footer()),
13593 28042 sid_map(nullptr),
13594
1/2
✓ Branch 0 taken 28042 times.
✗ Branch 1 not taken.
28042 snapshot_version(nullptr) {
13595
1/2
✓ Branch 0 taken 28042 times.
✗ Branch 1 not taken.
28042 DBUG_TRACE;
13596
2/4
✓ Branch 0 taken 28042 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28042 times.
28042 if (!is_valid()) return;
13597
13598 28042 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13599
13600
2/4
✓ Branch 0 taken 28042 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28042 times.
✗ Branch 3 not taken.
28042 sid_map = new Sid_map(nullptr);
13601
2/4
✓ Branch 0 taken 28042 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28042 times.
✗ Branch 3 not taken.
28042 snapshot_version = new Gtid_set(sid_map);
13602
1/2
✓ Branch 0 taken 28042 times.
✗ Branch 1 not taken.
28042 }
13603
13604 167262 Transaction_context_log_event::~Transaction_context_log_event() {
13605 83630 DBUG_TRACE;
13606
1/2
✓ Branch 0 taken 41816 times.
✗ Branch 1 not taken.
83632 if (server_uuid) my_free(const_cast<char *>(server_uuid));
13607 83632 server_uuid = nullptr;
13608
2/2
✓ Branch 0 taken 28042 times.
✓ Branch 1 taken 13774 times.
83632 if (encoded_snapshot_version)
13609 56084 my_free(const_cast<uchar *>(encoded_snapshot_version));
13610 83632 encoded_snapshot_version = nullptr;
13611
1/2
✓ Branch 0 taken 41816 times.
✗ Branch 1 not taken.
83632 delete snapshot_version;
13612
1/2
✓ Branch 0 taken 41816 times.
✗ Branch 1 not taken.
83632 delete sid_map;
13613 167264 }
13614
13615 size_t Transaction_context_log_event::to_string(char *buf, ulong len) const {
13616 DBUG_TRACE;
13617 return snprintf(buf, len, "server_uuid=%s\tthread_id=%u", server_uuid,
13618 thread_id);
13619 }
13620
13621 #ifdef MYSQL_SERVER
13622 int Transaction_context_log_event::pack_info(Protocol *protocol) {
13623 DBUG_TRACE;
13624 char buf[256];
13625 size_t bytes = to_string(buf, 256);
13626 protocol->store_string(buf, bytes, &my_charset_bin);
13627 return 0;
13628 }
13629 #endif
13630
13631 #ifndef MYSQL_SERVER
13632 void Transaction_context_log_event::print(
13633 FILE *, PRINT_EVENT_INFO *print_event_info) const {
13634 DBUG_TRACE;
13635 char buf[256];
13636 IO_CACHE *const head = &print_event_info->head_cache;
13637
13638 if (!print_event_info->short_form) {
13639 to_string(buf, 256);
13640 print_header(head, print_event_info, false);
13641 my_b_printf(head, "Transaction_context: %s\n", buf);
13642 }
13643 }
13644 #endif
13645
13646 #if defined(MYSQL_SERVER)
13647 int Transaction_context_log_event::do_update_pos(Relay_log_info *rli) {
13648 DBUG_TRACE;
13649 rli->inc_event_relay_log_pos();
13650 return 0;
13651 }
13652 #endif
13653
13654 27540 size_t Transaction_context_log_event::get_data_size() {
13655
1/2
✓ Branch 0 taken 27540 times.
✗ Branch 1 not taken.
27540 DBUG_TRACE;
13656
13657 27540 size_t size = Binary_log_event::TRANSACTION_CONTEXT_HEADER_LEN;
13658 27540 size += strlen(server_uuid);
13659
1/2
✓ Branch 0 taken 27540 times.
✗ Branch 1 not taken.
27540 size += get_snapshot_version_size();
13660
1/2
✓ Branch 0 taken 27540 times.
✗ Branch 1 not taken.
27540 size += get_data_set_size(&write_set);
13661
1/2
✓ Branch 0 taken 27540 times.
✗ Branch 1 not taken.
27540 size += get_data_set_size(&read_set);
13662
13663 27540 return size;
13664 27540 }
13665
13666 13772 size_t Transaction_context_log_event::get_event_length() {
13667 13772 return LOG_EVENT_HEADER_LEN + get_data_size();
13668 }
13669
13670 #ifdef MYSQL_SERVER
13671 13768 bool Transaction_context_log_event::write_data_header(Basic_ostream *ostream) {
13672
1/2
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
13768 DBUG_TRACE;
13673 char buf[Binary_log_event::TRANSACTION_CONTEXT_HEADER_LEN];
13674
13675 13768 buf[ENCODED_SERVER_UUID_LEN_OFFSET] = (char)strlen(server_uuid);
13676 13768 int4store(buf + ENCODED_THREAD_ID_OFFSET, thread_id);
13677 13768 buf[ENCODED_GTID_SPECIFIED_OFFSET] = gtid_specified;
13678 13768 int4store(buf + ENCODED_SNAPSHOT_VERSION_LEN_OFFSET,
13679
1/2
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
13768 get_snapshot_version_size());
13680 13768 int4store(buf + ENCODED_WRITE_SET_ITEMS_OFFSET, write_set.size());
13681 13768 int4store(buf + ENCODED_READ_SET_ITEMS_OFFSET, read_set.size());
13682
1/2
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
13768 return wrapper_my_b_safe_write(
13683 ostream, (const uchar *)buf,
13684 27536 Binary_log_event::TRANSACTION_CONTEXT_HEADER_LEN);
13685 13768 }
13686
13687 13768 bool Transaction_context_log_event::write_data_body(Basic_ostream *ostream) {
13688
1/2
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
13768 DBUG_TRACE;
13689
13690
1/2
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
13768 if (wrapper_my_b_safe_write(ostream, (const uchar *)server_uuid,
13691 13768 strlen(server_uuid)) ||
13692
6/12
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13768 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13768 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13768 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 13768 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 13768 times.
27536 write_snapshot_version(ostream) || write_data_set(ostream, &write_set) ||
13693
2/4
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13768 times.
13768 write_data_set(ostream, &read_set))
13694 return true;
13695
13696 13768 return false;
13697 13768 }
13698
13699 13768 bool Transaction_context_log_event::write_snapshot_version(
13700 Basic_ostream *ostream) {
13701
1/2
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
13768 DBUG_TRACE;
13702 13768 bool result = false;
13703
13704
1/2
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
13768 uint32 len = get_snapshot_version_size();
13705
1/2
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
13768 uchar *buffer = (uchar *)my_malloc(key_memory_log_event, len, MYF(MY_WME));
13706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13768 times.
13768 if (buffer == nullptr) return true;
13707
13708
1/2
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
13768 snapshot_version->encode(buffer);
13709
2/4
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13768 times.
13768 if (wrapper_my_b_safe_write(ostream, buffer, len)) result = true;
13710
13711
1/2
✓ Branch 0 taken 13768 times.
✗ Branch 1 not taken.
13768 my_free(buffer);
13712 13768 return result;
13713 13768 }
13714
13715 27536 bool Transaction_context_log_event::write_data_set(
13716 Basic_ostream *ostream, std::list<const char *> *set) {
13717
1/2
✓ Branch 0 taken 27536 times.
✗ Branch 1 not taken.
27536 DBUG_TRACE;
13718
2/2
✓ Branch 0 taken 231238 times.
✓ Branch 1 taken 27536 times.
258774 for (std::list<const char *>::iterator it = set->begin(); it != set->end();
13719 231238 ++it) {
13720 char buf[ENCODED_READ_WRITE_SET_ITEM_LEN];
13721 231238 const char *hash = *it;
13722 231238 uint16 len = strlen(hash);
13723
13724 231238 int2store(buf, len);
13725
1/2
✓ Branch 0 taken 231238 times.
✗ Branch 1 not taken.
231238 if (wrapper_my_b_safe_write(ostream, (const uchar *)buf,
13726
2/4
✓ Branch 0 taken 231238 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 231238 times.
462476 ENCODED_READ_WRITE_SET_ITEM_LEN) ||
13727
2/4
✓ Branch 0 taken 231238 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 231238 times.
231238 wrapper_my_b_safe_write(ostream, (const uchar *)hash, len))
13728 return true;
13729 }
13730
13731 27536 return false;
13732 27536 }
13733 #endif
13734
13735 28039 bool Transaction_context_log_event::read_snapshot_version() {
13736
1/2
✓ Branch 0 taken 28039 times.
✗ Branch 1 not taken.
28039 DBUG_TRACE;
13737
2/4
✓ Branch 0 taken 28039 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28039 times.
28039 assert(snapshot_version->is_empty());
13738
13739
1/2
✓ Branch 0 taken 28039 times.
✗ Branch 1 not taken.
28039 global_sid_lock->wrlock();
13740
1/2
✓ Branch 0 taken 28039 times.
✗ Branch 1 not taken.
28039 enum_return_status return_status = global_sid_map->copy(sid_map);
13741
1/2
✓ Branch 0 taken 28039 times.
✗ Branch 1 not taken.
28039 global_sid_lock->unlock();
13742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28039 times.
28039 if (return_status != RETURN_STATUS_OK) return true;
13743
13744 56078 return snapshot_version->add_gtid_encoding(encoded_snapshot_version,
13745
1/2
✓ Branch 0 taken 28039 times.
✗ Branch 1 not taken.
28039 encoded_snapshot_version_length) !=
13746 28039 RETURN_STATUS_OK;
13747 28039 }
13748
13749 55076 size_t Transaction_context_log_event::get_snapshot_version_size() {
13750
1/2
✓ Branch 0 taken 55076 times.
✗ Branch 1 not taken.
55076 DBUG_TRACE;
13751
1/2
✓ Branch 0 taken 55076 times.
✗ Branch 1 not taken.
55076 size_t result = snapshot_version->get_encoded_length();
13752 55076 return result;
13753 55076 }
13754
13755 55080 int Transaction_context_log_event::get_data_set_size(
13756 std::list<const char *> *set) {
13757
1/2
✓ Branch 0 taken 55080 times.
✗ Branch 1 not taken.
55080 DBUG_TRACE;
13758 55080 int size = 0;
13759
13760
2/2
✓ Branch 0 taken 462777 times.
✓ Branch 1 taken 55080 times.
517857 for (std::list<const char *>::iterator it = set->begin(); it != set->end();
13761 462777 ++it)
13762 462777 size += ENCODED_READ_WRITE_SET_ITEM_LEN + strlen(*it);
13763
13764 55080 return size;
13765 55080 }
13766
13767 231539 void Transaction_context_log_event::add_write_set(const char *hash) {
13768
1/2
✓ Branch 0 taken 231539 times.
✗ Branch 1 not taken.
231539 DBUG_TRACE;
13769
1/2
✓ Branch 0 taken 231539 times.
✗ Branch 1 not taken.
231539 write_set.push_back(hash);
13770 231539 }
13771
13772 void Transaction_context_log_event::add_read_set(const char *hash) {
13773 DBUG_TRACE;
13774 read_set.push_back(hash);
13775 }
13776
13777 /**************************************************************************
13778 View_change_log_event methods
13779 **************************************************************************/
13780
13781 #ifdef MYSQL_SERVER
13782 3811 View_change_log_event::View_change_log_event(const char *raw_view_id)
13783 : binary_log::View_change_event(raw_view_id),
13784 Log_event(header(), footer(), Log_event::EVENT_TRANSACTIONAL_CACHE,
13785
1/2
✓ Branch 0 taken 3811 times.
✗ Branch 1 not taken.
3811 Log_event::EVENT_NORMAL_LOGGING) {
13786
1/2
✓ Branch 0 taken 3811 times.
✗ Branch 1 not taken.
3811 DBUG_TRACE;
13787 3811 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13788
13789 3811 common_header->set_is_valid(strlen(view_id) != 0);
13790 3811 }
13791 #endif
13792
13793 8636 View_change_log_event::View_change_log_event(
13794 8636 const char *buffer, const Format_description_event *descr_event)
13795 : binary_log::View_change_event(buffer, descr_event),
13796
1/2
✓ Branch 0 taken 8006 times.
✗ Branch 1 not taken.
8636 Log_event(header(), footer()) {
13797
1/2
✓ Branch 0 taken 8636 times.
✗ Branch 1 not taken.
8636 DBUG_TRACE;
13798
3/4
✓ Branch 0 taken 8006 times.
✓ Branch 1 taken 630 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8006 times.
8636 if (!is_valid()) return;
13799 8636 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13800
13801 // Change the cache/logging types to allow writing to the binary log cache
13802 8636 event_cache_type = EVENT_TRANSACTIONAL_CACHE;
13803 8636 event_logging_type = EVENT_NORMAL_LOGGING;
13804
1/2
✓ Branch 0 taken 8636 times.
✗ Branch 1 not taken.
8636 }
13805
13806 49788 View_change_log_event::~View_change_log_event() {
13807 24894 DBUG_TRACE;
13808 24894 certification_info.clear();
13809 49788 }
13810
13811 9053 size_t View_change_log_event::get_data_size() {
13812
1/2
✓ Branch 0 taken 9053 times.
✗ Branch 1 not taken.
9053 DBUG_TRACE;
13813
13814 9053 size_t size = Binary_log_event::VIEW_CHANGE_HEADER_LEN;
13815
1/2
✓ Branch 0 taken 9053 times.
✗ Branch 1 not taken.
9053 size += get_size_data_map(&certification_info);
13816
13817 9053 return size;
13818 9053 }
13819
13820 9053 size_t View_change_log_event::get_size_data_map(
13821 std::map<std::string, std::string> *map) {
13822
1/2
✓ Branch 0 taken 9053 times.
✗ Branch 1 not taken.
9053 DBUG_TRACE;
13823 9053 size_t size = 0;
13824
13825 9053 std::map<std::string, std::string>::iterator iter;
13826 9053 size += (ENCODED_CERT_INFO_KEY_SIZE_LEN + ENCODED_CERT_INFO_VALUE_LEN) *
13827 9053 map->size();
13828
2/2
✓ Branch 0 taken 10997 times.
✓ Branch 1 taken 9053 times.
20050 for (iter = map->begin(); iter != map->end(); iter++)
13829 10997 size += iter->first.length() + iter->second.length();
13830
13831 9053 return size;
13832 9053 }
13833
13834 304 size_t View_change_log_event::to_string(char *buf, ulong len) const {
13835
1/2
✓ Branch 0 taken 304 times.
✗ Branch 1 not taken.
304 DBUG_TRACE;
13836 304 return snprintf(buf, len, "view_id=%s", view_id);
13837 304 }
13838
13839 #ifdef MYSQL_SERVER
13840 224 int View_change_log_event::pack_info(Protocol *protocol) {
13841
1/2
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
224 DBUG_TRACE;
13842 char buf[256];
13843
1/2
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
224 size_t bytes = to_string(buf, 256);
13844
1/2
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
224 protocol->store_string(buf, bytes, &my_charset_bin);
13845 224 return 0;
13846 224 }
13847 #endif
13848
13849 #ifndef MYSQL_SERVER
13850 80 void View_change_log_event::print(FILE *,
13851 PRINT_EVENT_INFO *print_event_info) const {
13852
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 DBUG_TRACE;
13853 char buf[256];
13854 80 IO_CACHE *const head = &print_event_info->head_cache;
13855
13856
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 if (!print_event_info->short_form) {
13857
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 to_string(buf, 256);
13858
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 print_header(head, print_event_info, false);
13859
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 my_b_printf(head, "View_change_log_event: %s\n", buf);
13860 }
13861 80 }
13862 #endif
13863
13864 #if defined(MYSQL_SERVER)
13865
13866 6636 int View_change_log_event::do_apply_event(Relay_log_info const *rli) {
13867 6636 enum_gtid_statement_status state = gtid_pre_statement_checks(thd);
13868
2/2
✓ Branch 0 taken 1386 times.
✓ Branch 1 taken 5250 times.
6636 if (state == GTID_STATEMENT_SKIP) return 0;
13869
13870
3/6
✓ Branch 0 taken 5250 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5250 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5250 times.
10500 if (state == GTID_STATEMENT_CANCEL ||
13871 5250 (state == GTID_STATEMENT_EXECUTE &&
13872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5250 times.
5250 gtid_pre_statement_post_implicit_commit_checks(thd))) {
13873 uint error = thd->get_stmt_da()->mysql_errno();
13874 assert(error != 0);
13875 rli->report(ERROR_LEVEL, error, "Error executing View Change event: '%s'",
13876 thd->get_stmt_da()->message_text());
13877 thd->is_slave_error = true;
13878 return -1;
13879 }
13880
13881
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5248 times.
5250 if (!opt_bin_log) {
13882 2 return 0;
13883 }
13884
13885 /*
13886 The view change is going to be written directly into the binary log and
13887 its "data_written" field may change depending on local binlog-checksum
13888 settings.
13889
13890 As MTS keep track of the size of the events on its queue relying on events
13891 header data_written field, we must ensure that it should not change on the
13892 event instance in memory (by backing it up before writing into binary log
13893 and restoring it after it was written).
13894 */
13895 5248 size_t original_ev_data_written = common_header->data_written;
13896 5248 int error = mysql_bin_log.write_event(this);
13897
1/2
✓ Branch 0 taken 5248 times.
✗ Branch 1 not taken.
5248 if (original_ev_data_written)
13898 5248 common_header->data_written = original_ev_data_written;
13899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5248 times.
5248 if (error)
13900 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
13901 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
13902 "Could not write the VIEW CHANGE event in the binary log.");
13903
13904 5248 return (error);
13905 }
13906
13907 int View_change_log_event::do_update_pos(Relay_log_info *rli) {
13908 DBUG_TRACE;
13909 rli->inc_event_relay_log_pos();
13910 return 0;
13911 }
13912
13913 9053 bool View_change_log_event::write_data_header(Basic_ostream *ostream) {
13914
1/2
✓ Branch 0 taken 9053 times.
✗ Branch 1 not taken.
9053 DBUG_TRACE;
13915 char buf[Binary_log_event::VIEW_CHANGE_HEADER_LEN];
13916
13917 9053 memcpy(buf, view_id, ENCODED_VIEW_ID_MAX_LEN);
13918 9053 int8store(buf + ENCODED_SEQ_NUMBER_OFFSET, seq_number);
13919 9053 int4store(buf + ENCODED_CERT_INFO_SIZE_OFFSET, certification_info.size());
13920
1/2
✓ Branch 0 taken 9053 times.
✗ Branch 1 not taken.
9053 return wrapper_my_b_safe_write(ostream, (const uchar *)buf,
13921 18106 Binary_log_event::VIEW_CHANGE_HEADER_LEN);
13922 9053 }
13923
13924 9053 bool View_change_log_event::write_data_body(Basic_ostream *ostream) {
13925
1/2
✓ Branch 0 taken 9053 times.
✗ Branch 1 not taken.
9053 DBUG_TRACE;
13926
13927
2/4
✓ Branch 0 taken 9053 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9053 times.
9053 if (write_data_map(ostream, &certification_info)) return true;
13928
13929 9053 return false;
13930 9053 }
13931
13932 9053 bool View_change_log_event::write_data_map(
13933 Basic_ostream *ostream, std::map<std::string, std::string> *map) {
13934
1/2
✓ Branch 0 taken 9053 times.
✗ Branch 1 not taken.
9053 DBUG_TRACE;
13935 9053 bool result = false;
13936
13937 9053 std::map<std::string, std::string>::iterator iter;
13938
2/2
✓ Branch 0 taken 10997 times.
✓ Branch 1 taken 9053 times.
20050 for (iter = map->begin(); iter != map->end(); iter++) {
13939 uchar buf_key_len[ENCODED_CERT_INFO_KEY_SIZE_LEN];
13940 10997 uint16 key_len = iter->first.length();
13941 10997 int2store(buf_key_len, key_len);
13942
13943 10997 const char *key = iter->first.c_str();
13944
13945 uchar buf_value_len[ENCODED_CERT_INFO_VALUE_LEN];
13946 10997 uint32 value_len = iter->second.length();
13947 10997 int4store(buf_value_len, value_len);
13948
13949 10997 const char *value = iter->second.c_str();
13950
13951
1/2
✓ Branch 0 taken 10997 times.
✗ Branch 1 not taken.
10997 if (wrapper_my_b_safe_write(ostream, buf_key_len,
13952 10997 ENCODED_CERT_INFO_KEY_SIZE_LEN) ||
13953
2/4
✓ Branch 0 taken 10997 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10997 times.
✗ Branch 3 not taken.
10997 wrapper_my_b_safe_write(ostream, (const uchar *)key, key_len) ||
13954
2/4
✓ Branch 0 taken 10997 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10997 times.
✗ Branch 3 not taken.
10997 wrapper_my_b_safe_write(ostream, buf_value_len,
13955
2/4
✓ Branch 0 taken 10997 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10997 times.
21994 ENCODED_CERT_INFO_VALUE_LEN) ||
13956
2/4
✓ Branch 0 taken 10997 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10997 times.
10997 wrapper_my_b_safe_write(ostream, (const uchar *)value, value_len))
13957 return result;
13958 }
13959
13960 9053 return false;
13961 9053 }
13962
13963 #endif // MYSQL_SERVER
13964
13965 /*
13966 Updates the certification info map.
13967 */
13968 3809 void View_change_log_event::set_certification_info(
13969 std::map<std::string, std::string> *info, size_t *event_size) {
13970
1/2
✓ Branch 0 taken 3809 times.
✗ Branch 1 not taken.
3809 DBUG_TRACE;
13971 3809 certification_info.clear();
13972
13973 3809 *event_size = Binary_log_event::VIEW_CHANGE_HEADER_LEN;
13974 3809 std::map<std::string, std::string>::iterator it;
13975
2/2
✓ Branch 0 taken 4958 times.
✓ Branch 1 taken 3809 times.
8767 for (it = info->begin(); it != info->end(); ++it) {
13976
1/2
✓ Branch 0 taken 4958 times.
✗ Branch 1 not taken.
4958 std::string key = it->first;
13977
1/2
✓ Branch 0 taken 4958 times.
✗ Branch 1 not taken.
4958 std::string value = it->second;
13978
2/4
✓ Branch 0 taken 4958 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4958 times.
✗ Branch 3 not taken.
4958 certification_info[key] = value;
13979 4958 *event_size += it->first.length() + it->second.length();
13980 4958 }
13981 3809 *event_size +=
13982 3809 (ENCODED_CERT_INFO_KEY_SIZE_LEN + ENCODED_CERT_INFO_VALUE_LEN) *
13983 3809 certification_info.size();
13984 3809 }
13985
13986 size_t Transaction_payload_log_event::get_data_size() {
13987 /* purecov: begin inspected */
13988 DBUG_TRACE;
13989 assert(false);
13990 return 0;
13991 /* purecov: end */
13992 }
13993
13994 #ifdef MYSQL_SERVER
13995 6 uint8 Transaction_payload_log_event::get_mts_dbs(Mts_db_names *arg,
13996 Rpl_filter *rpl_filter
13997 [[maybe_unused]]) {
13998 6 Mts_db_names &mts_dbs = m_applier_ctx.get_mts_db_names();
13999
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS) {
14000 4 arg->name[0] = nullptr;
14001 4 arg->num = OVER_MAX_DBS_IN_EVENT_MTS;
14002 } else {
14003
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (int i = 0; i < mts_dbs.num; i++) arg->name[i] = mts_dbs.name[i];
14004 2 arg->num = mts_dbs.num;
14005 }
14006
14007 6 return arg->num;
14008 }
14009
14010 6 void Transaction_payload_log_event::set_mts_dbs(Mts_db_names &arg) {
14011 6 m_applier_ctx.reset();
14012 6 Mts_db_names &mts_dbs = m_applier_ctx.get_mts_db_names();
14013 6 mts_dbs.num = arg.num;
14014
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (mts_dbs.num < MAX_DBS_IN_EVENT_MTS) {
14015
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (int i = 0; i < arg.num; i++)
14016 // strndup already adds the string terminator
14017 2 mts_dbs.name[i] = strndup(arg.name[i], NAME_LEN);
14018 }
14019 #ifndef NDEBUG
14020 else
14021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS);
14022 #endif
14023 6 }
14024
14025 6 uint8 Transaction_payload_log_event::mts_number_dbs() {
14026 6 return m_applier_ctx.get_mts_db_names().num;
14027 }
14028
14029 24 int Transaction_payload_log_event::do_apply_event(Relay_log_info const *rli) {
14030
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 DBUG_TRACE;
14031 24 int res = 0;
14032 24 PSI_stage_info old_stage;
14033
14034 /* apply events in the payload */
14035
14036 binary_log::transaction::compression::Iterable_buffer it(
14037
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 m_payload, m_payload_size, m_uncompressed_size, m_compression_type);
14038
14039
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 thd->enter_stage(&stage_binlog_transaction_decompress, &old_stage, __func__,
14040 __FILE__, __LINE__);
14041
8/14
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 150 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 144 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 168 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 168 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 150 times.
✓ Branch 13 taken 18 times.
168 for (auto ptr : it) {
14042
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 THD_STAGE_INFO(thd, old_stage);
14043
3/4
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 144 times.
150 if ((res = apply_payload_event(rli, (const uchar *)ptr))) break;
14044
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 thd->enter_stage(&stage_binlog_transaction_decompress, &old_stage, __func__,
14045 __FILE__, __LINE__);
14046 24 }
14047
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 THD_STAGE_INFO(thd, old_stage);
14048
14049 24 return res;
14050 24 }
14051
14052 300 static bool shall_delete_event_after_apply(Log_event *ev) {
14053 300 bool res = false;
14054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
300 if (ev == nullptr) return res;
14055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
300 switch (ev->get_type_code()) {
14056 case binary_log::FORMAT_DESCRIPTION_EVENT:
14057 /*
14058 Format_description_log_event should not be deleted because it will
14059 be used to read info about the relay log's format; it will be
14060 deleted when the SQL thread does not need it, i.e. when this
14061 thread terminates.
14062 */
14063
14064 [[fallthrough]];
14065 case binary_log::ROWS_QUERY_LOG_EVENT:
14066 /*
14067 ROWS_QUERY_LOG_EVENT is destroyed at the end of the current statement
14068 clean-up routine.
14069 */
14070 res = false;
14071 break;
14072 300 default:
14073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
300 DBUG_PRINT("info", ("Deleting the event after it has been executed"));
14074 300 res = true;
14075 300 break;
14076 }
14077
14078 300 return res;
14079 }
14080
14081 150 bool Transaction_payload_log_event::apply_payload_event(
14082 Relay_log_info const *rli, const uchar *event_buf) {
14083
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 DBUG_TRACE;
14084 150 bool res = false;
14085 150 const uchar *ptr = event_buf;
14086 150 Log_event *ev = nullptr;
14087 150 bool copied_buffer = false;
14088 150 uchar *copy_buffer = nullptr;
14089
14090 /*
14091 disable checksums - there are no checksums for events inside the tple
14092 otherwise, the last 4 bytes would be truncated.
14093
14094 We do this by copying the fdle from the rli. Then we disable the checksum
14095 in the copy. Then we use it to decode the events in the payload instead
14096 of the original fdle.
14097
14098 We allocate the fdle copy in the stack.
14099
14100 TODO: simplify this by breaking the binlog_event_deserialize API
14101 and make it take a single boolean instead that states whether the
14102 event has a checksum in it or not.
14103 */
14104 150 Format_description_event *fde = rli->get_rli_description_event();
14105
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 Format_description_log_event fdle(fde->reader().buffer(), fde);
14106 150 fdle.footer()->checksum_alg = binary_log::BINLOG_CHECKSUM_ALG_OFF;
14107 150 fdle.register_temp_buf(const_cast<char *>(fde->reader().buffer()), false);
14108 150 size_t event_len = uint4korr(ptr + EVENT_LEN_OFFSET);
14109
2/4
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 150 times.
150 if (binlog_event_deserialize(ptr, event_len, &fdle, true, &ev)) {
14110 res = true;
14111 goto end;
14112 }
14113
14114
2/4
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 150 times.
150 if (!shall_delete_event_after_apply(ev)) {
14115 copy_buffer =
14116 (uchar *)my_malloc(key_memory_log_event, event_len, MYF(MY_WME));
14117 memcpy(copy_buffer, ptr, event_len);
14118 copied_buffer = true;
14119 } else {
14120 150 copy_buffer = const_cast<uchar *>(ptr);
14121 150 copied_buffer = false;
14122 }
14123
14124 150 ev->register_temp_buf((char *)copy_buffer, copied_buffer);
14125 150 ev->common_header->log_pos = header()->log_pos;
14126
14127 150 thd->server_id = ev->server_id; // use the original server id for logging
14128 150 thd->unmasked_server_id = ev->common_header->unmasked_server_id;
14129
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 thd->set_time(); // time the query
14130
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 thd->lex->set_current_query_block(nullptr);
14131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
150 if (!ev->common_header->when.tv_sec)
14132 my_micro_time_to_timeval(my_micro_time(), &ev->common_header->when);
14133 150 ev->thd = thd; // because up to this point, ev->thd == 0
14134
14135 // TODO: HATE THIS
14136
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 24 times.
150 if (is_mts_worker(thd)) {
14137 126 auto worker =
14138 static_cast<Slave_worker *>(const_cast<Relay_log_info *>(rli));
14139 126 this->worker = worker;
14140
14141 // set in the event context
14142 126 ev->future_event_relay_log_pos = this->future_event_relay_log_pos;
14143 126 ev->mts_group_idx = mts_group_idx;
14144 126 ev->worker = worker;
14145
14146 // set in the worker context
14147 126 worker->set_future_event_relay_log_pos(ev->future_event_relay_log_pos);
14148 126 worker->set_master_log_pos(static_cast<ulong>(ev->common_header->log_pos));
14149 126 worker->set_gaq_index(ev->mts_group_idx);
14150
14151
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 104 times.
126 if (ev->get_type_code() == binary_log::QUERY_EVENT)
14152 static_cast<Query_log_event *>(ev)
14153 22 ->set_skip_temp_tables_handling_by_worker();
14154
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 res = ev->do_apply_event_worker(worker);
14155 } else {
14156 24 auto coord = const_cast<Relay_log_info *>(rli);
14157 24 ev->future_event_relay_log_pos = coord->get_future_event_relay_log_pos();
14158
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 res = ev->apply_event(coord);
14159 }
14160
14161
3/6
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 150 times.
✓ Branch 4 taken 150 times.
✗ Branch 5 not taken.
150 if (shall_delete_event_after_apply(ev)) delete ev;
14162
14163 end:
14164 150 return res;
14165 150 }
14166
14167 21 Log_event::enum_skip_reason Transaction_payload_log_event::do_shall_skip(
14168 Relay_log_info *rli) {
14169 21 return Log_event::do_shall_skip(rli);
14170 }
14171
14172 60 bool Transaction_payload_log_event::write(Basic_ostream *ostream) {
14173
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 DBUG_TRACE;
14174
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 auto codec = binary_log::codecs::Factory::build_codec(header()->type_code);
14175 60 auto buffer_size = MAX_DATA_LENGTH + LOG_EVENT_HEADER_LEN;
14176 unsigned char buffer[MAX_DATA_LENGTH + LOG_EVENT_HEADER_LEN];
14177
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 auto result = codec->encode(*this, buffer, buffer_size);
14178 60 size_t data_size = result.first + m_payload_size;
14179
14180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 if (result.second == true) goto end;
14181
14182
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 return write_header(ostream, data_size) ||
14183
2/4
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
60 wrapper_my_b_safe_write(ostream, (uchar *)buffer, result.first) ||
14184
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 wrapper_my_b_safe_write(ostream,
14185
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 reinterpret_cast<const uchar *>(m_payload),
14186
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
120 m_payload_size) ||
14187
2/4
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 60 times.
120 write_footer(ostream);
14188 end:
14189 return true;
14190 60 }
14191
14192 37 int Transaction_payload_log_event::pack_info(Protocol *protocol) {
14193
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 std::ostringstream oss;
14194
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 oss << "compression='";
14195
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
74 oss << binary_log::transaction::compression::type_to_string(
14196
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 m_compression_type);
14197
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 oss << "', decompressed_size=";
14198
2/4
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
37 oss << m_uncompressed_size << " bytes";
14199
2/4
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
37 protocol->store(oss.str().c_str(), &my_charset_bin);
14200 37 return 0;
14201 37 }
14202
14203 154 bool Transaction_payload_log_event::ends_group() const { return true; }
14204
14205 #endif
14206
14207 #ifndef MYSQL_SERVER
14208 /**
14209 The default values for these variables should be values that are
14210 *incorrect*, i.e., values that cannot occur in an event. This way,
14211 they will always be printed for the first event.
14212 */
14213 4485 PRINT_EVENT_INFO::PRINT_EVENT_INFO()
14214 4485 : flags2_inited(false),
14215 4485 sql_mode_inited(false),
14216 4485 sql_mode(0),
14217 4485 auto_increment_increment(0),
14218 4485 auto_increment_offset(0),
14219 4485 charset_inited(false),
14220 4485 lc_time_names_number(~0),
14221 4485 charset_database_number(ILLEGAL_CHARSET_INFO_NUMBER),
14222 4485 default_collation_for_utf8mb4_number(ILLEGAL_CHARSET_INFO_NUMBER),
14223 4485 sql_require_primary_key(0xff),
14224 4485 thread_id(0),
14225 4485 thread_id_printed(false),
14226 4485 default_table_encryption(0xff),
14227 4485 base64_output_mode(BASE64_OUTPUT_UNSPEC),
14228 4485 printed_fd_event(false),
14229 4485 have_unflushed_events(false),
14230
1/2
✓ Branch 0 taken 4485 times.
✗ Branch 1 not taken.
4485 skipped_event_in_transaction(false) {
14231 /*
14232 Currently we only use static PRINT_EVENT_INFO objects, so zeroed at
14233 program's startup, but these explicit memset() is for the day someone
14234 creates dynamic instances.
14235 */
14236 4485 memset(db, 0, sizeof(db));
14237 4485 memset(charset, 0, sizeof(charset));
14238 4485 memset(time_zone_str, 0, sizeof(time_zone_str));
14239 4485 delimiter[0] = ';';
14240 4485 delimiter[1] = 0;
14241 4485 myf const flags = MYF(MY_WME | MY_NABP);
14242
1/2
✓ Branch 0 taken 4485 times.
✗ Branch 1 not taken.
4485 open_cached_file(&head_cache, nullptr, nullptr, 0, flags);
14243
1/2
✓ Branch 0 taken 4485 times.
✗ Branch 1 not taken.
4485 open_cached_file(&body_cache, nullptr, nullptr, 0, flags);
14244
1/2
✓ Branch 0 taken 4485 times.
✗ Branch 1 not taken.
4485 open_cached_file(&footer_cache, nullptr, nullptr, 0, flags);
14245 4485 }
14246 #endif
14247
14248 #if defined(MYSQL_SERVER)
14249 1 Heartbeat_log_event::Heartbeat_log_event(
14250 1 const char *buf, const Format_description_event *description_event)
14251 : binary_log::Heartbeat_event(buf, description_event),
14252
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 Log_event(header(), footer()) {
14253
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 DBUG_TRACE;
14254 1 }
14255
14256 3414 Heartbeat_log_event_v2::Heartbeat_log_event_v2(
14257 3414 const char *buf, const Format_description_event *description_event)
14258 : binary_log::Heartbeat_event_v2(buf, description_event),
14259
1/2
✓ Branch 0 taken 3414 times.
✗ Branch 1 not taken.
3414 Log_event(header(), footer()) {
14260
1/2
✓ Branch 0 taken 3414 times.
✗ Branch 1 not taken.
3414 DBUG_TRACE;
14261 3414 }
14262 #endif
14263
14264 #ifdef MYSQL_SERVER
14265 /*
14266 This is a utility function that adds a quoted identifier into the a buffer.
14267 This also escapes any existence of the quote string inside the identifier.
14268
14269 SYNOPSIS
14270 my_strmov_quoted_identifier
14271 thd thread handler
14272 buffer target buffer
14273 identifier the identifier to be quoted
14274 length length of the identifier
14275 */
14276 81 size_t my_strmov_quoted_identifier(THD *thd, char *buffer,
14277 const char *identifier, size_t length) {
14278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 int q = thd ? get_quote_char_for_identifier(thd, identifier, length) : '`';
14279 81 return my_strmov_quoted_identifier_helper(q, buffer, identifier, length);
14280 }
14281 #else
14282 43609 size_t my_strmov_quoted_identifier(char *buffer, const char *identifier) {
14283 43609 int q = '`';
14284 43609 return my_strmov_quoted_identifier_helper(q, buffer, identifier, 0);
14285 }
14286
14287 #endif
14288
14289 43690 size_t my_strmov_quoted_identifier_helper(int q, char *buffer,
14290 const char *identifier,
14291 size_t length) {
14292 43690 size_t written = 0;
14293 char quote_char;
14294
2/2
✓ Branch 0 taken 43628 times.
✓ Branch 1 taken 62 times.
43690 size_t id_length = (length) ? length : strlen(identifier);
14295
14296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43690 times.
43690 if (q == EOF) {
14297 (void)strncpy(buffer, identifier, id_length);
14298 return id_length;
14299 }
14300 43690 quote_char = (char)q;
14301 43690 *buffer++ = quote_char;
14302 43690 written++;
14303
2/2
✓ Branch 0 taken 166183 times.
✓ Branch 1 taken 43690 times.
209873 while (id_length--) {
14304
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 166160 times.
166183 if (*identifier == quote_char) {
14305 23 *buffer++ = quote_char;
14306 23 written++;
14307 }
14308 166183 *buffer++ = *identifier++;
14309 166183 written++;
14310 }
14311 43690 *buffer++ = quote_char;
14312 43690 return ++written;
14313 }
14314
14315 306882 std::pair<bool, binary_log::Log_event_basic_info> extract_log_event_basic_info(
14316 Log_event *log_event) {
14317
1/2
✓ Branch 0 taken 306882 times.
✗ Branch 1 not taken.
306882 DBUG_TRACE;
14318
14319 306882 binary_log::Log_event_basic_info event_info;
14320 306882 event_info.query_length = 0;
14321 306882 event_info.event_type = log_event->get_type_code();
14322
14323
2/2
✓ Branch 0 taken 35648 times.
✓ Branch 1 taken 271234 times.
306882 if (binary_log::QUERY_EVENT == event_info.event_type) {
14324 35648 Query_log_event *qlog_event = static_cast<Query_log_event *>(log_event);
14325 35648 event_info.query = qlog_event->query;
14326
1/2
✓ Branch 0 taken 35648 times.
✗ Branch 1 not taken.
35648 if (event_info.query != nullptr)
14327 35648 event_info.query_length = strlen(event_info.query);
14328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35648 times.
35648 if (event_info.query_length == 0) {
14329 assert(event_info.query == nullptr); /* purecov: inspected */
14330 return std::make_pair(true, event_info); /* purecov: inspected */
14331 }
14332 }
14333 306882 event_info.ignorable_event = log_event->is_ignorable_event();
14334
1/2
✓ Branch 0 taken 306882 times.
✗ Branch 1 not taken.
306882 return std::make_pair(false, event_info);
14335 306882 }
14336
14337 1817434 std::pair<bool, binary_log::Log_event_basic_info> extract_log_event_basic_info(
14338 const char *buf, size_t length,
14339 const binary_log::Format_description_event *fd_event) {
14340
1/2
✓ Branch 0 taken 1817434 times.
✗ Branch 1 not taken.
1817434 DBUG_TRACE;
14341
14342 1817434 binary_log::Log_event_basic_info event_info;
14343 1817434 event_info.query_length = 0;
14344
14345 1817434 uint header_size = fd_event->common_header_len;
14346 1817434 const char *query = nullptr;
14347
14348 /* Error if the event content is smaller than header size for the format */
14349
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1817434 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1817434 if (length < header_size) return std::make_pair(true, event_info);
14350
14351 1817434 event_info.event_type = (Log_event_type)buf[EVENT_TYPE_OFFSET];
14352
14353
2/2
✓ Branch 0 taken 573711 times.
✓ Branch 1 taken 1243723 times.
1817434 if (binary_log::QUERY_EVENT == event_info.event_type) {
14354 573711 event_info.query_length =
14355
1/2
✓ Branch 0 taken 573700 times.
✗ Branch 1 not taken.
573711 Query_log_event::get_query(buf, length, fd_event, &query);
14356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 573711 times.
573711 if (event_info.query_length == 0) {
14357 assert(query == nullptr); /* purecov: inspected */
14358 return std::make_pair(true, event_info); /* purecov: inspected */
14359 }
14360 573711 event_info.query = query;
14361 }
14362 1817434 event_info.ignorable_event =
14363 1817434 uint2korr(buf + FLAGS_OFFSET) & LOG_EVENT_IGNORABLE_F;
14364
1/2
✓ Branch 0 taken 1817434 times.
✗ Branch 1 not taken.
1817434 return std::make_pair(false, event_info);
14365 1817434 }
14366